From 4599c79723212d233dacd6267b50ff42057fa489 Mon Sep 17 00:00:00 2001 From: alazhar Date: Thu, 2 Jan 2020 23:02:57 +0700 Subject: [PATCH] first commit --- .htaccess | 15 + README.md | 0 application/.htaccess | 1 + application/cache/.htaccess | 1 + application/cache/index.html | 10 + application/config/autoload.php | 116 + application/config/config.php | 362 + application/config/constants.php | 41 + application/config/database.php | 74 + application/config/doctypes.php | 15 + application/config/foreign_chars.php | 64 + application/config/hooks.php | 16 + application/config/index.html | 10 + application/config/migration.php | 41 + application/config/mimes.php | 106 + application/config/profiler.php | 17 + application/config/routes.php | 46 + application/config/smileys.php | 66 + application/config/user_agents.php | 178 + application/controllers/contoh hasil.txt | 106 + application/controllers/form.php | 558 + application/controllers/index.html | 10 + application/controllers/user.php | 149 + application/core/index.html | 10 + application/errors/error_404.php | 62 + application/errors/error_db.php | 62 + application/errors/error_general.php | 62 + application/errors/error_php.php | 10 + application/errors/index.html | 10 + application/helpers/index.html | 10 + application/hooks/index.html | 10 + application/index.html | 10 + application/language/english/index.html | 10 + application/libraries/auth.php | 62 + application/libraries/index.html | 10 + application/logs/index.html | 10 + application/models/M_form.php | 211 + application/models/index.html | 10 + application/third_party/index.html | 10 + application/views/admin/bAdmin.php | 185 + application/views/bForm.php | 823 ++ application/views/bHalamanAdmin.php | 336 + application/views/bReview.php | 828 ++ application/views/index.html | 10 + application/views/vAdmin.php | 163 + application/views/vAdminForm.php | 94 + application/views/vAdminSellingout.php | 178 + application/views/vAdminStaff.php | 94 + application/views/vAdminVolume.php | 226 + application/views/vForm2.php | 924 ++ application/views/vLogin.php | 81 + application/views/vReview.php | 920 ++ asset/bootstrap/css/bootstrap-responsive.css | 1109 ++ .../css/bootstrap-responsive.min.css | 9 + asset/bootstrap/css/bootstrap.css | 6194 +++++++++ asset/bootstrap/css/bootstrap.min.css | 9 + asset/bootstrap/css/docs.css | 1067 ++ .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes asset/bootstrap/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes asset/bootstrap/js/README.md | 106 + asset/bootstrap/js/application.js | 156 + asset/bootstrap/js/bootstrap-affix.js | 117 + asset/bootstrap/js/bootstrap-alert.js | 99 + asset/bootstrap/js/bootstrap-button.js | 105 + asset/bootstrap/js/bootstrap-carousel.js | 207 + asset/bootstrap/js/bootstrap-collapse.js | 167 + asset/bootstrap/js/bootstrap-dropdown.js | 169 + asset/bootstrap/js/bootstrap-modal.js | 247 + asset/bootstrap/js/bootstrap-popover.js | 114 + asset/bootstrap/js/bootstrap-scrollspy.js | 162 + asset/bootstrap/js/bootstrap-tab.js | 144 + asset/bootstrap/js/bootstrap-tooltip.js | 361 + asset/bootstrap/js/bootstrap-transition.js | 60 + asset/bootstrap/js/bootstrap-typeahead.js | 335 + asset/bootstrap/js/bootstrap.js | 2280 ++++ asset/bootstrap/js/bootstrap.min.js | 6 + .../js/google-code-prettify/prettify.css | 30 + .../js/google-code-prettify/prettify.js | 28 + asset/bootstrap/js/holder/holder.js | 401 + asset/bootstrap/js/html5shiv.js | 8 + asset/bootstrap/js/jquery.js | 5 + asset/css/style.css | 48 + asset/img/ajax_loading.gif | Bin 0 -> 404 bytes asset/img/ajax_loading3.gif | Bin 0 -> 723 bytes asset/img/file_add.png | Bin 0 -> 4086 bytes asset/img/loading7.gif | Bin 0 -> 8233 bytes asset/img/loading81.gif | Bin 0 -> 18311 bytes asset/js/form_view.js | 311 + asset/js/jquery.maskedinput.min.js | 7 + asset/sliderform/jquery.slideto.v1.1.js | 50 + asset/sliderform/sliding.form.js | 154 + asset/sliderform/style.css | 152 + asset/slimscroll/jquery-ui.js | 11363 ++++++++++++++++ asset/slimscroll/jquery.slimscroll.min.js | 15 + asset/tablesorter/demo_table.css | 577 + asset/tablesorter/images/Sorting icons.psd | Bin 0 -> 27490 bytes asset/tablesorter/images/back_disabled.png | Bin 0 -> 1361 bytes asset/tablesorter/images/back_enabled.png | Bin 0 -> 1379 bytes .../tablesorter/images/back_enabled_hover.png | Bin 0 -> 1375 bytes asset/tablesorter/images/favicon.ico | Bin 0 -> 894 bytes asset/tablesorter/images/forward_disabled.png | Bin 0 -> 1363 bytes asset/tablesorter/images/forward_enabled.png | Bin 0 -> 1380 bytes .../images/forward_enabled_hover.png | Bin 0 -> 1379 bytes asset/tablesorter/images/sort_asc.png | Bin 0 -> 1118 bytes .../tablesorter/images/sort_asc_disabled.png | Bin 0 -> 1050 bytes asset/tablesorter/images/sort_both.png | Bin 0 -> 1136 bytes asset/tablesorter/images/sort_desc.png | Bin 0 -> 1127 bytes .../tablesorter/images/sort_desc_disabled.png | Bin 0 -> 1045 bytes asset/tablesorter/jquery.dataTables.min.js | 155 + asset/tablesorter/jquery.js | 2 + everseiko.zip | Bin 0 -> 863523 bytes favicon.ico | Bin 0 -> 4286 bytes index.php | 205 + license.txt | 51 + system/.htaccess | 1 + system/core/Benchmark.php | 118 + system/core/CodeIgniter.php | 402 + system/core/Common.php | 564 + system/core/Config.php | 379 + system/core/Controller.php | 64 + system/core/Exceptions.php | 193 + system/core/Hooks.php | 248 + system/core/Input.php | 849 ++ system/core/Lang.php | 160 + system/core/Loader.php | 1248 ++ system/core/Model.php | 57 + system/core/Output.php | 574 + system/core/Router.php | 522 + system/core/Security.php | 876 ++ system/core/URI.php | 654 + system/core/Utf8.php | 165 + system/core/index.html | 10 + system/database/DB.php | 162 + system/database/DB_active_rec.php | 2045 +++ system/database/DB_cache.php | 195 + system/database/DB_driver.php | 1410 ++ system/database/DB_forge.php | 382 + system/database/DB_result.php | 410 + system/database/DB_utility.php | 414 + .../database/drivers/cubrid/cubrid_driver.php | 792 ++ .../database/drivers/cubrid/cubrid_forge.php | 288 + .../database/drivers/cubrid/cubrid_result.php | 202 + .../drivers/cubrid/cubrid_utility.php | 108 + system/database/drivers/cubrid/index.html | 10 + system/database/drivers/index.html | 10 + system/database/drivers/mssql/index.html | 10 + .../database/drivers/mssql/mssql_driver.php | 667 + system/database/drivers/mssql/mssql_forge.php | 248 + .../database/drivers/mssql/mssql_result.php | 169 + .../database/drivers/mssql/mssql_utility.php | 88 + system/database/drivers/mysql/index.html | 10 + .../database/drivers/mysql/mysql_driver.php | 779 ++ system/database/drivers/mysql/mysql_forge.php | 273 + .../database/drivers/mysql/mysql_result.php | 174 + .../database/drivers/mysql/mysql_utility.php | 210 + system/database/drivers/mysqli/index.html | 10 + .../database/drivers/mysqli/mysqli_driver.php | 776 ++ .../database/drivers/mysqli/mysqli_forge.php | 258 + .../database/drivers/mysqli/mysqli_result.php | 174 + .../drivers/mysqli/mysqli_utility.php | 87 + system/database/drivers/oci8/index.html | 10 + system/database/drivers/oci8/oci8_driver.php | 808 ++ system/database/drivers/oci8/oci8_forge.php | 248 + system/database/drivers/oci8/oci8_result.php | 217 + system/database/drivers/oci8/oci8_utility.php | 87 + system/database/drivers/odbc/index.html | 10 + system/database/drivers/odbc/odbc_driver.php | 637 + system/database/drivers/odbc/odbc_forge.php | 266 + system/database/drivers/odbc/odbc_result.php | 228 + system/database/drivers/odbc/odbc_utility.php | 103 + system/database/drivers/pdo/index.html | 10 + system/database/drivers/pdo/pdo_driver.php | 812 ++ system/database/drivers/pdo/pdo_forge.php | 266 + system/database/drivers/pdo/pdo_result.php | 183 + system/database/drivers/pdo/pdo_utility.php | 103 + system/database/drivers/postgre/index.html | 10 + .../drivers/postgre/postgre_driver.php | 703 + .../drivers/postgre/postgre_forge.php | 299 + .../drivers/postgre/postgre_result.php | 169 + .../drivers/postgre/postgre_utility.php | 88 + system/database/drivers/sqlite/index.html | 10 + .../database/drivers/sqlite/sqlite_driver.php | 658 + .../database/drivers/sqlite/sqlite_forge.php | 265 + .../database/drivers/sqlite/sqlite_result.php | 179 + .../drivers/sqlite/sqlite_utility.php | 96 + system/database/drivers/sqlsrv/index.html | 10 + .../database/drivers/sqlsrv/sqlsrv_driver.php | 599 + .../database/drivers/sqlsrv/sqlsrv_forge.php | 248 + .../database/drivers/sqlsrv/sqlsrv_result.php | 169 + .../drivers/sqlsrv/sqlsrv_utility.php | 88 + system/database/index.html | 10 + system/fonts/index.html | 10 + system/fonts/texb.ttf | Bin 0 -> 143830 bytes system/helpers/array_helper.php | 119 + system/helpers/captcha_helper.php | 246 + system/helpers/cookie_helper.php | 103 + system/helpers/date_helper.php | 611 + system/helpers/directory_helper.php | 80 + system/helpers/download_helper.php | 107 + system/helpers/email_helper.php | 62 + system/helpers/file_helper.php | 479 + system/helpers/form_helper.php | 1054 ++ system/helpers/html_helper.php | 436 + system/helpers/index.html | 10 + system/helpers/inflector_helper.php | 203 + system/helpers/language_helper.php | 58 + system/helpers/number_helper.php | 76 + system/helpers/path_helper.php | 72 + system/helpers/security_helper.php | 128 + system/helpers/smiley_helper.php | 281 + system/helpers/string_helper.php | 307 + system/helpers/text_helper.php | 535 + system/helpers/typography_helper.php | 93 + system/helpers/url_helper.php | 594 + system/helpers/xml_helper.php | 71 + system/index.html | 10 + system/language/english/calendar_lang.php | 51 + system/language/english/date_lang.php | 61 + system/language/english/db_lang.php | 29 + system/language/english/email_lang.php | 24 + .../language/english/form_validation_lang.php | 29 + system/language/english/ftp_lang.php | 18 + system/language/english/imglib_lang.php | 24 + system/language/english/index.html | 10 + system/language/english/migration_lang.php | 13 + system/language/english/number_lang.php | 10 + system/language/english/profiler_lang.php | 25 + system/language/english/unit_test_lang.php | 25 + system/language/english/upload_lang.php | 22 + system/language/index.html | 10 + system/libraries/Cache/Cache.php | 216 + system/libraries/Cache/drivers/Cache_apc.php | 151 + .../libraries/Cache/drivers/Cache_dummy.php | 129 + system/libraries/Cache/drivers/Cache_file.php | 195 + .../Cache/drivers/Cache_memcached.php | 218 + system/libraries/Calendar.php | 475 + system/libraries/Cart.php | 552 + system/libraries/Driver.php | 229 + system/libraries/Email.php | 2092 +++ system/libraries/Encrypt.php | 547 + system/libraries/Form_validation.php | 1382 ++ system/libraries/Ftp.php | 660 + system/libraries/Image_lib.php | 1537 +++ system/libraries/Javascript.php | 871 ++ system/libraries/Log.php | 114 + system/libraries/Migration.php | 328 + system/libraries/Pagination.php | 340 + system/libraries/Parser.php | 212 + system/libraries/Profiler.php | 558 + system/libraries/Session.php | 780 ++ system/libraries/Sha1.php | 251 + system/libraries/Table.php | 531 + system/libraries/Trackback.php | 548 + system/libraries/Typography.php | 410 + system/libraries/Unit_test.php | 383 + system/libraries/Upload.php | 1136 ++ system/libraries/User_agent.php | 549 + system/libraries/Xmlrpc.php | 1423 ++ system/libraries/Xmlrpcs.php | 612 + system/libraries/Zip.php | 423 + system/libraries/index.html | 10 + system/libraries/javascript/Jquery.php | 1071 ++ tambahan.txt | 12 + 263 files changed, 84293 insertions(+) create mode 100644 .htaccess create mode 100644 README.md create mode 100644 application/.htaccess create mode 100644 application/cache/.htaccess create mode 100644 application/cache/index.html create mode 100644 application/config/autoload.php create mode 100644 application/config/config.php create mode 100644 application/config/constants.php create mode 100644 application/config/database.php create mode 100644 application/config/doctypes.php create mode 100644 application/config/foreign_chars.php create mode 100644 application/config/hooks.php create mode 100644 application/config/index.html create mode 100644 application/config/migration.php create mode 100644 application/config/mimes.php create mode 100644 application/config/profiler.php create mode 100644 application/config/routes.php create mode 100644 application/config/smileys.php create mode 100644 application/config/user_agents.php create mode 100644 application/controllers/contoh hasil.txt create mode 100644 application/controllers/form.php create mode 100644 application/controllers/index.html create mode 100644 application/controllers/user.php create mode 100644 application/core/index.html create mode 100644 application/errors/error_404.php create mode 100644 application/errors/error_db.php create mode 100644 application/errors/error_general.php create mode 100644 application/errors/error_php.php create mode 100644 application/errors/index.html create mode 100644 application/helpers/index.html create mode 100644 application/hooks/index.html create mode 100644 application/index.html create mode 100644 application/language/english/index.html create mode 100644 application/libraries/auth.php create mode 100644 application/libraries/index.html create mode 100644 application/logs/index.html create mode 100644 application/models/M_form.php create mode 100644 application/models/index.html create mode 100644 application/third_party/index.html create mode 100644 application/views/admin/bAdmin.php create mode 100644 application/views/bForm.php create mode 100644 application/views/bHalamanAdmin.php create mode 100644 application/views/bReview.php create mode 100644 application/views/index.html create mode 100644 application/views/vAdmin.php create mode 100644 application/views/vAdminForm.php create mode 100644 application/views/vAdminSellingout.php create mode 100644 application/views/vAdminStaff.php create mode 100644 application/views/vAdminVolume.php create mode 100644 application/views/vForm2.php create mode 100644 application/views/vLogin.php create mode 100644 application/views/vReview.php create mode 100644 asset/bootstrap/css/bootstrap-responsive.css create mode 100644 asset/bootstrap/css/bootstrap-responsive.min.css create mode 100644 asset/bootstrap/css/bootstrap.css create mode 100644 asset/bootstrap/css/bootstrap.min.css create mode 100644 asset/bootstrap/css/docs.css create mode 100644 asset/bootstrap/img/glyphicons-halflings-white.png create mode 100644 asset/bootstrap/img/glyphicons-halflings.png create mode 100644 asset/bootstrap/js/README.md create mode 100644 asset/bootstrap/js/application.js create mode 100644 asset/bootstrap/js/bootstrap-affix.js create mode 100644 asset/bootstrap/js/bootstrap-alert.js create mode 100644 asset/bootstrap/js/bootstrap-button.js create mode 100644 asset/bootstrap/js/bootstrap-carousel.js create mode 100644 asset/bootstrap/js/bootstrap-collapse.js create mode 100644 asset/bootstrap/js/bootstrap-dropdown.js create mode 100644 asset/bootstrap/js/bootstrap-modal.js create mode 100644 asset/bootstrap/js/bootstrap-popover.js create mode 100644 asset/bootstrap/js/bootstrap-scrollspy.js create mode 100644 asset/bootstrap/js/bootstrap-tab.js create mode 100644 asset/bootstrap/js/bootstrap-tooltip.js create mode 100644 asset/bootstrap/js/bootstrap-transition.js create mode 100644 asset/bootstrap/js/bootstrap-typeahead.js create mode 100644 asset/bootstrap/js/bootstrap.js create mode 100644 asset/bootstrap/js/bootstrap.min.js create mode 100644 asset/bootstrap/js/google-code-prettify/prettify.css create mode 100644 asset/bootstrap/js/google-code-prettify/prettify.js create mode 100644 asset/bootstrap/js/holder/holder.js create mode 100644 asset/bootstrap/js/html5shiv.js create mode 100644 asset/bootstrap/js/jquery.js create mode 100644 asset/css/style.css create mode 100644 asset/img/ajax_loading.gif create mode 100644 asset/img/ajax_loading3.gif create mode 100644 asset/img/file_add.png create mode 100644 asset/img/loading7.gif create mode 100644 asset/img/loading81.gif create mode 100644 asset/js/form_view.js create mode 100644 asset/js/jquery.maskedinput.min.js create mode 100644 asset/sliderform/jquery.slideto.v1.1.js create mode 100644 asset/sliderform/sliding.form.js create mode 100644 asset/sliderform/style.css create mode 100644 asset/slimscroll/jquery-ui.js create mode 100644 asset/slimscroll/jquery.slimscroll.min.js create mode 100644 asset/tablesorter/demo_table.css create mode 100644 asset/tablesorter/images/Sorting icons.psd create mode 100644 asset/tablesorter/images/back_disabled.png create mode 100644 asset/tablesorter/images/back_enabled.png create mode 100644 asset/tablesorter/images/back_enabled_hover.png create mode 100644 asset/tablesorter/images/favicon.ico create mode 100644 asset/tablesorter/images/forward_disabled.png create mode 100644 asset/tablesorter/images/forward_enabled.png create mode 100644 asset/tablesorter/images/forward_enabled_hover.png create mode 100644 asset/tablesorter/images/sort_asc.png create mode 100644 asset/tablesorter/images/sort_asc_disabled.png create mode 100644 asset/tablesorter/images/sort_both.png create mode 100644 asset/tablesorter/images/sort_desc.png create mode 100644 asset/tablesorter/images/sort_desc_disabled.png create mode 100644 asset/tablesorter/jquery.dataTables.min.js create mode 100644 asset/tablesorter/jquery.js create mode 100644 everseiko.zip create mode 100644 favicon.ico create mode 100644 index.php create mode 100644 license.txt create mode 100644 system/.htaccess create mode 100644 system/core/Benchmark.php create mode 100644 system/core/CodeIgniter.php create mode 100644 system/core/Common.php create mode 100644 system/core/Config.php create mode 100644 system/core/Controller.php create mode 100644 system/core/Exceptions.php create mode 100644 system/core/Hooks.php create mode 100644 system/core/Input.php create mode 100644 system/core/Lang.php create mode 100644 system/core/Loader.php create mode 100644 system/core/Model.php create mode 100644 system/core/Output.php create mode 100644 system/core/Router.php create mode 100644 system/core/Security.php create mode 100644 system/core/URI.php create mode 100644 system/core/Utf8.php create mode 100644 system/core/index.html create mode 100644 system/database/DB.php create mode 100644 system/database/DB_active_rec.php create mode 100644 system/database/DB_cache.php create mode 100644 system/database/DB_driver.php create mode 100644 system/database/DB_forge.php create mode 100644 system/database/DB_result.php create mode 100644 system/database/DB_utility.php create mode 100644 system/database/drivers/cubrid/cubrid_driver.php create mode 100644 system/database/drivers/cubrid/cubrid_forge.php create mode 100644 system/database/drivers/cubrid/cubrid_result.php create mode 100644 system/database/drivers/cubrid/cubrid_utility.php create mode 100644 system/database/drivers/cubrid/index.html create mode 100644 system/database/drivers/index.html create mode 100644 system/database/drivers/mssql/index.html create mode 100644 system/database/drivers/mssql/mssql_driver.php create mode 100644 system/database/drivers/mssql/mssql_forge.php create mode 100644 system/database/drivers/mssql/mssql_result.php create mode 100644 system/database/drivers/mssql/mssql_utility.php create mode 100644 system/database/drivers/mysql/index.html create mode 100644 system/database/drivers/mysql/mysql_driver.php create mode 100644 system/database/drivers/mysql/mysql_forge.php create mode 100644 system/database/drivers/mysql/mysql_result.php create mode 100644 system/database/drivers/mysql/mysql_utility.php create mode 100644 system/database/drivers/mysqli/index.html create mode 100644 system/database/drivers/mysqli/mysqli_driver.php create mode 100644 system/database/drivers/mysqli/mysqli_forge.php create mode 100644 system/database/drivers/mysqli/mysqli_result.php create mode 100644 system/database/drivers/mysqli/mysqli_utility.php create mode 100644 system/database/drivers/oci8/index.html create mode 100644 system/database/drivers/oci8/oci8_driver.php create mode 100644 system/database/drivers/oci8/oci8_forge.php create mode 100644 system/database/drivers/oci8/oci8_result.php create mode 100644 system/database/drivers/oci8/oci8_utility.php create mode 100644 system/database/drivers/odbc/index.html create mode 100644 system/database/drivers/odbc/odbc_driver.php create mode 100644 system/database/drivers/odbc/odbc_forge.php create mode 100644 system/database/drivers/odbc/odbc_result.php create mode 100644 system/database/drivers/odbc/odbc_utility.php create mode 100644 system/database/drivers/pdo/index.html create mode 100644 system/database/drivers/pdo/pdo_driver.php create mode 100644 system/database/drivers/pdo/pdo_forge.php create mode 100644 system/database/drivers/pdo/pdo_result.php create mode 100644 system/database/drivers/pdo/pdo_utility.php create mode 100644 system/database/drivers/postgre/index.html create mode 100644 system/database/drivers/postgre/postgre_driver.php create mode 100644 system/database/drivers/postgre/postgre_forge.php create mode 100644 system/database/drivers/postgre/postgre_result.php create mode 100644 system/database/drivers/postgre/postgre_utility.php create mode 100644 system/database/drivers/sqlite/index.html create mode 100644 system/database/drivers/sqlite/sqlite_driver.php create mode 100644 system/database/drivers/sqlite/sqlite_forge.php create mode 100644 system/database/drivers/sqlite/sqlite_result.php create mode 100644 system/database/drivers/sqlite/sqlite_utility.php create mode 100644 system/database/drivers/sqlsrv/index.html create mode 100644 system/database/drivers/sqlsrv/sqlsrv_driver.php create mode 100644 system/database/drivers/sqlsrv/sqlsrv_forge.php create mode 100644 system/database/drivers/sqlsrv/sqlsrv_result.php create mode 100644 system/database/drivers/sqlsrv/sqlsrv_utility.php create mode 100644 system/database/index.html create mode 100644 system/fonts/index.html create mode 100644 system/fonts/texb.ttf create mode 100644 system/helpers/array_helper.php create mode 100644 system/helpers/captcha_helper.php create mode 100644 system/helpers/cookie_helper.php create mode 100644 system/helpers/date_helper.php create mode 100644 system/helpers/directory_helper.php create mode 100644 system/helpers/download_helper.php create mode 100644 system/helpers/email_helper.php create mode 100644 system/helpers/file_helper.php create mode 100644 system/helpers/form_helper.php create mode 100644 system/helpers/html_helper.php create mode 100644 system/helpers/index.html create mode 100644 system/helpers/inflector_helper.php create mode 100644 system/helpers/language_helper.php create mode 100644 system/helpers/number_helper.php create mode 100644 system/helpers/path_helper.php create mode 100644 system/helpers/security_helper.php create mode 100644 system/helpers/smiley_helper.php create mode 100644 system/helpers/string_helper.php create mode 100644 system/helpers/text_helper.php create mode 100644 system/helpers/typography_helper.php create mode 100644 system/helpers/url_helper.php create mode 100644 system/helpers/xml_helper.php create mode 100644 system/index.html create mode 100644 system/language/english/calendar_lang.php create mode 100644 system/language/english/date_lang.php create mode 100644 system/language/english/db_lang.php create mode 100644 system/language/english/email_lang.php create mode 100644 system/language/english/form_validation_lang.php create mode 100644 system/language/english/ftp_lang.php create mode 100644 system/language/english/imglib_lang.php create mode 100644 system/language/english/index.html create mode 100644 system/language/english/migration_lang.php create mode 100644 system/language/english/number_lang.php create mode 100644 system/language/english/profiler_lang.php create mode 100644 system/language/english/unit_test_lang.php create mode 100644 system/language/english/upload_lang.php create mode 100644 system/language/index.html create mode 100644 system/libraries/Cache/Cache.php create mode 100644 system/libraries/Cache/drivers/Cache_apc.php create mode 100644 system/libraries/Cache/drivers/Cache_dummy.php create mode 100644 system/libraries/Cache/drivers/Cache_file.php create mode 100644 system/libraries/Cache/drivers/Cache_memcached.php create mode 100644 system/libraries/Calendar.php create mode 100644 system/libraries/Cart.php create mode 100644 system/libraries/Driver.php create mode 100644 system/libraries/Email.php create mode 100644 system/libraries/Encrypt.php create mode 100644 system/libraries/Form_validation.php create mode 100644 system/libraries/Ftp.php create mode 100644 system/libraries/Image_lib.php create mode 100644 system/libraries/Javascript.php create mode 100644 system/libraries/Log.php create mode 100644 system/libraries/Migration.php create mode 100644 system/libraries/Pagination.php create mode 100644 system/libraries/Parser.php create mode 100644 system/libraries/Profiler.php create mode 100644 system/libraries/Session.php create mode 100644 system/libraries/Sha1.php create mode 100644 system/libraries/Table.php create mode 100644 system/libraries/Trackback.php create mode 100644 system/libraries/Typography.php create mode 100644 system/libraries/Unit_test.php create mode 100644 system/libraries/Upload.php create mode 100644 system/libraries/User_agent.php create mode 100644 system/libraries/Xmlrpc.php create mode 100644 system/libraries/Xmlrpcs.php create mode 100644 system/libraries/Zip.php create mode 100644 system/libraries/index.html create mode 100644 system/libraries/javascript/Jquery.php create mode 100644 tambahan.txt diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..a03b0e6 --- /dev/null +++ b/.htaccess @@ -0,0 +1,15 @@ +RewriteEngine On + +# Put your installation directory here: +# If your URL is www.example.com/, use / +# If your URL is www.example.com/site_folder/, use /site_folder/ + +RewriteBase /everseiko + +# Do not enable rewriting for files or directories that exist +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +# For reuests that are not actual files or directories, +# Rewrite to index.php/URL +RewriteRule ^(.*)$ index.php/$1 [PT,L] diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/application/.htaccess b/application/.htaccess new file mode 100644 index 0000000..14249c5 --- /dev/null +++ b/application/.htaccess @@ -0,0 +1 @@ +Deny from all \ No newline at end of file diff --git a/application/cache/.htaccess b/application/cache/.htaccess new file mode 100644 index 0000000..3418e55 --- /dev/null +++ b/application/cache/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/application/cache/index.html b/application/cache/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/cache/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/config/autoload.php b/application/config/autoload.php new file mode 100644 index 0000000..736a869 --- /dev/null +++ b/application/config/autoload.php @@ -0,0 +1,116 @@ + '', + 'xhtml1-strict' => '', + 'xhtml1-trans' => '', + 'xhtml1-frame' => '', + 'html5' => '', + 'html4-strict' => '', + 'html4-trans' => '', + 'html4-frame' => '' + ); + +/* End of file doctypes.php */ +/* Location: ./application/config/doctypes.php */ \ No newline at end of file diff --git a/application/config/foreign_chars.php b/application/config/foreign_chars.php new file mode 100644 index 0000000..14b0d73 --- /dev/null +++ b/application/config/foreign_chars.php @@ -0,0 +1,64 @@ + 'ae', + '/ö|œ/' => 'oe', + '/ü/' => 'ue', + '/Ä/' => 'Ae', + '/Ü/' => 'Ue', + '/Ö/' => 'Oe', + '/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ/' => 'A', + '/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª/' => 'a', + '/Ç|Ć|Ĉ|Ċ|Č/' => 'C', + '/ç|ć|ĉ|ċ|č/' => 'c', + '/Ð|Ď|Đ/' => 'D', + '/ð|ď|đ/' => 'd', + '/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě/' => 'E', + '/è|é|ê|ë|ē|ĕ|ė|ę|ě/' => 'e', + '/Ĝ|Ğ|Ġ|Ģ/' => 'G', + '/ĝ|ğ|ġ|ģ/' => 'g', + '/Ĥ|Ħ/' => 'H', + '/ĥ|ħ/' => 'h', + '/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ/' => 'I', + '/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı/' => 'i', + '/Ĵ/' => 'J', + '/ĵ/' => 'j', + '/Ķ/' => 'K', + '/ķ/' => 'k', + '/Ĺ|Ļ|Ľ|Ŀ|Ł/' => 'L', + '/ĺ|ļ|ľ|ŀ|ł/' => 'l', + '/Ñ|Ń|Ņ|Ň/' => 'N', + '/ñ|ń|ņ|ň|ʼn/' => 'n', + '/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ/' => 'O', + '/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º/' => 'o', + '/Ŕ|Ŗ|Ř/' => 'R', + '/ŕ|ŗ|ř/' => 'r', + '/Ś|Ŝ|Ş|Š/' => 'S', + '/ś|ŝ|ş|š|ſ/' => 's', + '/Ţ|Ť|Ŧ/' => 'T', + '/ţ|ť|ŧ/' => 't', + '/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ/' => 'U', + '/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ/' => 'u', + '/Ý|Ÿ|Ŷ/' => 'Y', + '/ý|ÿ|ŷ/' => 'y', + '/Ŵ/' => 'W', + '/ŵ/' => 'w', + '/Ź|Ż|Ž/' => 'Z', + '/ź|ż|ž/' => 'z', + '/Æ|Ǽ/' => 'AE', + '/ß/'=> 'ss', + '/IJ/' => 'IJ', + '/ij/' => 'ij', + '/Œ/' => 'OE', + '/ƒ/' => 'f' +); + +/* End of file foreign_chars.php */ +/* Location: ./application/config/foreign_chars.php */ \ No newline at end of file diff --git a/application/config/hooks.php b/application/config/hooks.php new file mode 100644 index 0000000..a4ad2be --- /dev/null +++ b/application/config/hooks.php @@ -0,0 +1,16 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/config/migration.php b/application/config/migration.php new file mode 100644 index 0000000..df42a3c --- /dev/null +++ b/application/config/migration.php @@ -0,0 +1,41 @@ +migration->latest() this is the version that schema will +| be upgraded / downgraded to. +| +*/ +$config['migration_version'] = 0; + + +/* +|-------------------------------------------------------------------------- +| Migrations Path +|-------------------------------------------------------------------------- +| +| Path to your migrations folder. +| Typically, it will be within your application path. +| Also, writing permission is required within the migrations path. +| +*/ +$config['migration_path'] = APPPATH . 'migrations/'; + + +/* End of file migration.php */ +/* Location: ./application/config/migration.php */ \ No newline at end of file diff --git a/application/config/mimes.php b/application/config/mimes.php new file mode 100644 index 0000000..100f7d4 --- /dev/null +++ b/application/config/mimes.php @@ -0,0 +1,106 @@ + 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'), + 'bin' => 'application/macbinary', + 'dms' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'exe' => array('application/octet-stream', 'application/x-msdownload'), + 'class' => 'application/octet-stream', + 'psd' => 'application/x-photoshop', + 'so' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => array('application/pdf', 'application/x-download'), + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => array('application/excel', 'application/vnd.ms-excel', 'application/msexcel'), + 'ppt' => array('application/powerpoint', 'application/vnd.ms-powerpoint'), + 'wbxml' => 'application/wbxml', + 'wmlc' => 'application/wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'gz' => 'application/x-gzip', + 'php' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php3' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'js' => 'application/x-javascript', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => array('application/x-tar', 'application/x-gzip-compressed'), + 'xhtml' => 'application/xhtml+xml', + 'xht' => 'application/xhtml+xml', + 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'), + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mpga' => 'audio/mpeg', + 'mp2' => 'audio/mpeg', + 'mp3' => array('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'), + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'rv' => 'video/vnd.rn-realvideo', + 'wav' => array('audio/x-wav', 'audio/wave', 'audio/wav'), + 'bmp' => array('image/bmp', 'image/x-windows-bmp'), + 'gif' => 'image/gif', + 'jpeg' => array('image/jpeg', 'image/pjpeg'), + 'jpg' => array('image/jpeg', 'image/pjpeg'), + 'jpe' => array('image/jpeg', 'image/pjpeg'), + 'png' => array('image/png', 'image/x-png'), + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', + 'shtml' => 'text/html', + 'txt' => 'text/plain', + 'text' => 'text/plain', + 'log' => array('text/plain', 'text/x-log'), + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie', + 'doc' => 'application/msword', + 'docx' => array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip'), + 'xlsx' => array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip'), + 'word' => array('application/msword', 'application/octet-stream'), + 'xl' => 'application/excel', + 'eml' => 'message/rfc822', + 'json' => array('application/json', 'text/json') + ); + + +/* End of file mimes.php */ +/* Location: ./application/config/mimes.php */ diff --git a/application/config/profiler.php b/application/config/profiler.php new file mode 100644 index 0000000..f8a5b1a --- /dev/null +++ b/application/config/profiler.php @@ -0,0 +1,17 @@ + array('grin.gif', '19', '19', 'grin'), + ':lol:' => array('lol.gif', '19', '19', 'LOL'), + ':cheese:' => array('cheese.gif', '19', '19', 'cheese'), + ':)' => array('smile.gif', '19', '19', 'smile'), + ';-)' => array('wink.gif', '19', '19', 'wink'), + ';)' => array('wink.gif', '19', '19', 'wink'), + ':smirk:' => array('smirk.gif', '19', '19', 'smirk'), + ':roll:' => array('rolleyes.gif', '19', '19', 'rolleyes'), + ':-S' => array('confused.gif', '19', '19', 'confused'), + ':wow:' => array('surprise.gif', '19', '19', 'surprised'), + ':bug:' => array('bigsurprise.gif', '19', '19', 'big surprise'), + ':-P' => array('tongue_laugh.gif', '19', '19', 'tongue laugh'), + '%-P' => array('tongue_rolleye.gif', '19', '19', 'tongue rolleye'), + ';-P' => array('tongue_wink.gif', '19', '19', 'tongue wink'), + ':P' => array('raspberry.gif', '19', '19', 'raspberry'), + ':blank:' => array('blank.gif', '19', '19', 'blank stare'), + ':long:' => array('longface.gif', '19', '19', 'long face'), + ':ohh:' => array('ohh.gif', '19', '19', 'ohh'), + ':grrr:' => array('grrr.gif', '19', '19', 'grrr'), + ':gulp:' => array('gulp.gif', '19', '19', 'gulp'), + '8-/' => array('ohoh.gif', '19', '19', 'oh oh'), + ':down:' => array('downer.gif', '19', '19', 'downer'), + ':red:' => array('embarrassed.gif', '19', '19', 'red face'), + ':sick:' => array('sick.gif', '19', '19', 'sick'), + ':shut:' => array('shuteye.gif', '19', '19', 'shut eye'), + ':-/' => array('hmm.gif', '19', '19', 'hmmm'), + '>:(' => array('mad.gif', '19', '19', 'mad'), + ':mad:' => array('mad.gif', '19', '19', 'mad'), + '>:-(' => array('angry.gif', '19', '19', 'angry'), + ':angry:' => array('angry.gif', '19', '19', 'angry'), + ':zip:' => array('zip.gif', '19', '19', 'zipper'), + ':kiss:' => array('kiss.gif', '19', '19', 'kiss'), + ':ahhh:' => array('shock.gif', '19', '19', 'shock'), + ':coolsmile:' => array('shade_smile.gif', '19', '19', 'cool smile'), + ':coolsmirk:' => array('shade_smirk.gif', '19', '19', 'cool smirk'), + ':coolgrin:' => array('shade_grin.gif', '19', '19', 'cool grin'), + ':coolhmm:' => array('shade_hmm.gif', '19', '19', 'cool hmm'), + ':coolmad:' => array('shade_mad.gif', '19', '19', 'cool mad'), + ':coolcheese:' => array('shade_cheese.gif', '19', '19', 'cool cheese'), + ':vampire:' => array('vampire.gif', '19', '19', 'vampire'), + ':snake:' => array('snake.gif', '19', '19', 'snake'), + ':exclaim:' => array('exclaim.gif', '19', '19', 'excaim'), + ':question:' => array('question.gif', '19', '19', 'question') // no comma after last item + + ); + +/* End of file smileys.php */ +/* Location: ./application/config/smileys.php */ \ No newline at end of file diff --git a/application/config/user_agents.php b/application/config/user_agents.php new file mode 100644 index 0000000..e2d3c3a --- /dev/null +++ b/application/config/user_agents.php @@ -0,0 +1,178 @@ + 'Windows Longhorn', + 'windows nt 5.2' => 'Windows 2003', + 'windows nt 5.0' => 'Windows 2000', + 'windows nt 5.1' => 'Windows XP', + 'windows nt 4.0' => 'Windows NT 4.0', + 'winnt4.0' => 'Windows NT 4.0', + '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', + 'ppc mac' => 'Power PC Mac', + 'freebsd' => 'FreeBSD', + 'ppc' => 'Macintosh', + 'linux' => 'Linux', + 'debian' => 'Debian', + 'sunos' => 'Sun Solaris', + 'beos' => 'BeOS', + 'apachebench' => 'ApacheBench', + 'aix' => 'AIX', + 'irix' => 'Irix', + 'osf' => 'DEC OSF', + 'hp-ux' => 'HP-UX', + 'netbsd' => 'NetBSD', + 'bsdi' => 'BSDi', + 'openbsd' => 'OpenBSD', + 'gnu' => 'GNU/Linux', + '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. +$browsers = array( + 'Flock' => 'Flock', + 'Chrome' => 'Chrome', + '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', + 'Safari' => 'Safari', + 'Mozilla' => 'Mozilla', + 'Konqueror' => 'Konqueror', + 'icab' => 'iCab', + 'Lynx' => 'Lynx', + 'Links' => 'Links', + 'hotjava' => 'HotJava', + 'amaya' => 'Amaya', + 'IBrowse' => 'IBrowse' + ); + +$mobiles = array( + // legacy array, old values commented out + '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' + + // Phones and Manufacturers + 'motorola' => "Motorola", + 'nokia' => "Nokia", + 'palm' => "Palm", + 'iphone' => "Apple iPhone", + 'ipad' => "iPad", + 'ipod' => "Apple iPod Touch", + 'sony' => "Sony Ericsson", + 'ericsson' => "Sony Ericsson", + 'blackberry' => "BlackBerry", + 'cocoon' => "O2 Cocoon", + 'blazer' => "Treo", + 'lg' => "LG", + 'amoi' => "Amoi", + 'xda' => "XDA", + 'mda' => "MDA", + 'vario' => "Vario", + 'htc' => "HTC", + 'samsung' => "Samsung", + 'sharp' => "Sharp", + 'sie-' => "Siemens", + 'alcatel' => "Alcatel", + 'benq' => "BenQ", + 'ipaq' => "HP iPaq", + 'mot-' => "Motorola", + 'playstation portable' => "PlayStation Portable", + 'hiptop' => "Danger Hiptop", + 'nec-' => "NEC", + 'panasonic' => "Panasonic", + 'philips' => "Philips", + 'sagem' => "Sagem", + 'sanyo' => "Sanyo", + 'spv' => "SPV", + 'zte' => "ZTE", + 'sendo' => "Sendo", + + // Operating Systems + 'symbian' => "Symbian", + 'SymbianOS' => "SymbianOS", + 'elaine' => "Palm", + 'palm' => "Palm", + 'series60' => "Symbian S60", + 'windows ce' => "Windows CE", + + // Browsers + 'obigo' => "Obigo", + 'netfront' => "Netfront Browser", + 'openwave' => "Openwave Browser", + 'mobilexplorer' => "Mobile Explorer", + 'operamini' => "Opera Mini", + 'opera mini' => "Opera Mini", + + // Other + 'digital paths' => "Digital Paths", + 'avantgo' => "AvantGo", + 'xiino' => "Xiino", + 'novarra' => "Novarra Transcoder", + 'vodafone' => "Vodafone", + 'docomo' => "NTT DoCoMo", + 'o2' => "O2", + + // Fallback + 'mobile' => "Generic Mobile", + 'wireless' => "Generic Mobile", + 'j2me' => "Generic Mobile", + 'midp' => "Generic Mobile", + 'cldc' => "Generic Mobile", + 'up.link' => "Generic Mobile", + 'up.browser' => "Generic Mobile", + 'smartphone' => "Generic Mobile", + 'cellphone' => "Generic Mobile" + ); + +// There are hundreds of bots but these are the most common. +$robots = array( + 'googlebot' => 'Googlebot', + 'msnbot' => 'MSNBot', + 'slurp' => 'Inktomi Slurp', + 'yahoo' => 'Yahoo', + 'askjeeves' => 'AskJeeves', + 'fastcrawler' => 'FastCrawler', + 'infoseek' => 'InfoSeek Robot 1.0', + 'lycos' => 'Lycos' + ); + +/* End of file user_agents.php */ +/* Location: ./application/config/user_agents.php */ \ No newline at end of file diff --git a/application/controllers/contoh hasil.txt b/application/controllers/contoh hasil.txt new file mode 100644 index 0000000..1e2dd35 --- /dev/null +++ b/application/controllers/contoh hasil.txt @@ -0,0 +1,106 @@ +//print_r($data) +Array ( +[province] => Jawa Barat +[city] => Bandung +[method] => Disuruh +[staffofscene] => GM +[customername] => Tarjo +[ind/comp] => Individual +[head_address] => PGA +[head_phone] => 123 +[branch_address] => Sukapura +[branch_phone] => 456 +[cp_name] => Azhar +[cp_phone] => 789 +[nature_bisnis] => Transportation,Minning,Expedition/Courier,Angkot +[loads] => Materials,Passenger,Soil,Orang +[destinations] => Dayeuh Kolot +[road_condition_good] => 60 +[road_condition_toll] => 10 +[road_condition_bad] => 70 +[road_condition_other] => 20 +[tire_brands] => Goodyear,Dunlop,Maxxis,Swallow +[tire_purchases] => Retreads +[tire_types] => Radial +[mileage_method] => Estimates +[mileage_front] => 300 +[mileage_rear] => 100 +[mileage_detail] => Mati +[purchase_method] => Estimates +[psi_front] => 230 +[condition_front] => +[psi_rear] => 330 +[otr] => Mampus +[problem] => Gak bisa jalan +) +//post() + Array ( + [cdProvince] => Jawa Barat + [cdKota] => Bandung + [rbCd] => Disuruh + [cdSos] => GM + [cdCusName] => Tarjo + [rbCd2] => Individual + [cdOffice] => PGA + [cdTelp] => 123 + [cdBranch] => Sukapura + [cdTelp2] => 456 + [cdcpname] => Azhar + [cdcpphone] => 789 + [cdCb_1] => Transportation + [cdCb_3] => Minning + [cdCb_4] => Expedition/Courier + [cdCb_5] => Angkot + [vdTr4] => + [vdTr6] => + [vdTr10] => + [vdLt6] => + [vdLt8] => + [vdLt10] => + [vdLt12] => + [vdLt14] => + [vdLt18] => + [vdLtot] => + [vdQtrType] => + [vdQtrQty] => + [vdQtrTyre] => + [vdQtrType2] => + [vdQtrQty2] => + [vdQtrTyre2] => + [vdCb_1] => Materials + [vdCb_2] => Passenger + [vdCb_4] => Soil + [vdCb_6] => Orang + [vdTr4wt] => + [vdTr6wt] => + [vdTr10wt] => + [vdLt6wt] => + [vdLt8wt] => + [vdLt10wt] => + [vdLt12wt] => + [vdLt14wt] => + [vdLt18wt] => + [vdLtotwt] => + [vdDest] => Dayeuh Kolot + [vdgoro] => 60 + [vdtoro] => 10 + [vdbaro] => 70 + [vdothers] => 20 + [tpCb_2] => Goodyear + [tpCb_5] => Dunlop + [tpCb_11] => Maxxis + [tpCb_14] => Swallow + [tpCb2_2] => Retreads + [tpCb3_4] => Radial + [trRb] => Estimates + [trmfront] => 300 + [trmrear] => 100 + [trmdetails] => Mati + [trfpsi] => 230 + [cb31] => Estimates + [trrpsi] => 330 + [cb3] => Actual + [trotr] => Mampus + [trproblem] => Gak bisa jalan + [send] => Submit + ) \ No newline at end of file diff --git a/application/controllers/form.php b/application/controllers/form.php new file mode 100644 index 0000000..cc23cea --- /dev/null +++ b/application/controllers/form.php @@ -0,0 +1,558 @@ +load->model('M_form'); + } + + function index() + { + if($this->auth->CI->session->userdata('is_log_in')){ + $this->load->view('vForm2'); + } + else{ + $this->load->view('vlogin'); + } + $array_items = array('status' => '', 'tipe' => '', 'message' => ''); + $this->session->unset_userdata($array_items); + } + + //view form untuk admin + function view_form($action,$id) + { + $data['action']=$action; + //$data['form']=$this->M_form->getVisit($id); + $data['id']= $id; + $this->load->view('vReview', $data); + } + + //get + function getDataAjax($id) + { + //$id = 7; + $data['customer'] = $this->M_form->getCust($id); + $data['visit'] = $this->M_form->getVisit($id); + $data['vehicle'] = $this->M_form->getVehicle($id); + $data['purchase'] = $this->M_form->getPurchase($id); + $data['recommendation'] = $this->M_form->getRecommendation($id); + $data['pictures'] = $this->M_form->getPictures($id); + + echo JSON_ENCODE($data); + } + + //load customer name + function searchcustomer($clu) + { + $data = $this->M_form->searchcustomer($clu); + echo JSON_ENCODE($data); + } + + //update status isApprove form + function isApprove($id) + { + $cds = array ( + '1' => $this->input->POST('modalcb1'), + '2' => $this->input->POST('modalcb2'), + '3' => $this->input->POST('modalcb3') + ); + $cds = array_filter($cds, 'strlen'); + $cds = implode(',' ,$cds); + $data = array ( + 'id_customer' => $this->input->POST('ID'), + 'tier' => $this->input->POST('tier'), + 'customer_data_status' => $cds, + 'isApprove' => 1 + ); + $this->M_form->isApprove($data, $id); + $notif = array( + 'status' => '1', + 'tipe' => 'alert-success', + 'message' => 'Well Done | Form is approved' + ); + $this->session->set_userdata($notif); + redirect('user','refresh'); + } + + //updateform + function updateform($id) + { + $notif = array( + 'status' => '1', + 'tipe' => 'alert-success', + 'message' => 'Well Done | Form Updated' + ); + $this->session->set_userdata($notif); + redirect('user','refresh'); + } + + //submit form + function form_submit() + { + //customer + $datacustomer = array ( + 'id' => '', + 'id_user' => '', + 'nama' => $this->input->POST('cdCusName'), + 'tipe' => $this->input->POST('rbCd2') + ); + + //visit + $nature_bisnis = array ( + '1' => $this->input->POST('cdCb_1'), + '2' => $this->input->POST('cdCb_2'), + '3' => $this->input->POST('cdCb_3'), + '4' => $this->input->POST('cdCb_4'), + '5' => $this->input->POST('cdCb_5'), + '6' => $this->input->POST('cdCb_6'), + '7' => $this->input->POST('cdCb_7') + ); + $nature_bisnis = array_filter($nature_bisnis, 'strlen'); + $nature_bisnis = implode(',' ,$nature_bisnis); + + $type_of_loads =""; + $type_of_loads = array ( + '1' => $this->input->POST('vdCb_1'), + '2' => $this->input->POST('vdCb_2'), + '3' => $this->input->POST('vdCb_3'), + '4' => $this->input->POST('vdCb_4'), + '5' => $this->input->POST('vdCb_5'), + '6' => $this->input->POST('vdCb_6') + ); + $type_of_loads = array_filter($type_of_loads, 'strlen'); + $type_of_loads = implode(',' ,$type_of_loads); + + $tyre_brands = array ( + '1' => $this->input->POST('tpCb_1'), + '2' => $this->input->POST('tpCb_2'), + '3' => $this->input->POST('tpCb_3'), + '4' => $this->input->POST('tpCb_4'), + '5' => $this->input->POST('tpCb_5'), + '6' => $this->input->POST('tpCb_6'), + '7' => $this->input->POST('tpCb_7'), + '8' => $this->input->POST('tpCb_8'), + '9' => $this->input->POST('tpCb_9'), + '10' => $this->input->POST('tpCb_10'), + '11' => $this->input->POST('tpCb_11'), + '12' => $this->input->POST('tpCb_12'), + '13' => $this->input->POST('tpCb_13'), + '14' => $this->input->POST('tpCb_14'), + '15' => $this->input->POST('tpCb_15') + ); + $tyre_brands = array_filter($tyre_brands, 'strlen'); + $tyre_brands = implode(',' ,$tyre_brands); + + $tyre_purchase = array ( + '1' => $this->input->POST('tpCb2_1'), + '2' => $this->input->POST('tpCb2_2') + ); + $tyre_purchase = array_filter($tyre_purchase, 'strlen'); + $tyre_purchase = implode(',' ,$tyre_purchase); + + $tire_types = array ( + '1' => $this->input->POST('tpCb3_1'), + '2' => $this->input->POST('tpCb3_2'), + '3' => $this->input->POST('tpCb3_3'), + '4' => $this->input->POST('tpCb3_4') + ); + $tire_types = array_filter($tire_types, 'strlen'); + $tire_types = implode(',' ,$tire_types); + + $cond_front = array ( + '1' => $this->input->POST('cb31'), + '2' => $this->input->POST('cb32') + ); + $cond_front = array_filter($cond_front, 'strlen'); + $cond_front = implode(',' ,$cond_front); + + $cond_rear = array ( + '1' => $this->input->POST('cb41'), + '2' => $this->input->POST('cb42') + ); + $cond_rear = array_filter($cond_rear, 'strlen'); + $cond_rear = implode(',' ,$cond_rear); + + if ($this->input->POST('rbCd')=="Other")$method = $this->input->POST('rbCdO'); + else $method = $this->input->POST('rbCd'); + + $datavisit = array ( + 'id' => '', + 'longitude' => '', + 'latitude' => '', + 'province' => $this->input->POST('cdProvince'), + 'kota' => $this->input->POST('cdKota'), + 'date_visit' => date('Y-m-d H:j:s'), + 'id_staff' => '', + 'id_customer' => '', + 'visit_status' => $method, + 'head_address' => $this->input->POST('cdOffice'), + 'head_phone' => $this->input->POST('cdTelp'), + 'branch_address' => $this->input->POST('cdBranch'), + 'branch_phone' => $this->input->POST('cdTelp2'), + 'cp_name' => $this->input->POST('cdcpname'), + 'cp_phone' => $this->input->POST('cdcpphone'), + 'nature_bisnis' => $nature_bisnis, + 'loads' => $type_of_loads, + 'destination' => $this->input->POST('vdDest'), + 'road_condition_good' => $this->input->POST('vdgoro'), + 'road_condition_toll' => $this->input->POST('vdtoro'), + 'road_condition_bad' => $this->input->POST('vdbaro'), + 'road_condition_other' => $this->input->POST('vdothers'), + 'tire_brands' => $tyre_brands, + 'tire_purchases' => $tyre_purchase, + 'tire_types' => $tire_types, + 'tire_other' => '', + 'mileage_method' => $this->input->POST('trRb'), + 'mileage_front' => $this->input->POST('trmfront'), + 'mileage_rear' => $this->input->POST('trmrear'), + 'mileage_detail' => $this->input->POST('trmdetails'), + 'purchase_method' => $this->input->POST('trRb2'), + 'purchase_number' => $this->input->POST(''), + 'psi_front' => $this->input->POST('trfpsi'), + 'condition_front' => $cond_rear, + 'psi_rear' => $this->input->POST('trrpsi'), + 'condition_rear' => $cond_front, + 'otr' => $this->input->POST('trotr'), + 'problem' => $this->input->POST('trproblem'), + 'notes' => '', + 'pictures' => '', + 'sender' => $this->input->POST('cdSos'), + 'customer' => $this->input->POST('cdCusName'), + 'tier' => '', + 'customer_data_status' => '', + 'qty' => '', + 'category' => '' + ); + + //customer vehicle + $datavehicle = ''; + $i = 0; + if ($this->input->POST('vdTr4')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Light', + 'qty' => $this->input->POST('vdTr4'), + 'total_tire' => '4', + 'load_weight' => $this->input->POST('vdTr4wt') + ); + $i++; + } + if ($this->input->POST('vdTr6')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Light', + 'qty' => $this->input->POST('vdTr6'), + 'total_tire' => '6', + 'load_weight' => $this->input->POST('vdTr6wt') + ); + $i++; + } + if ($this->input->POST('vdTr10')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Light', + 'qty' => $this->input->POST('vdTr10'), + 'total_tire' => '10', + 'load_weight' => $this->input->POST('vdTr10wt') + ); + $i++; + } + if ($this->input->POST('vdLt6')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLt6'), + 'total_tire' => '6', + 'load_weight' => $this->input->POST('vdLt6wt') + ); + $i++; + } + if ($this->input->POST('vdLt8')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLt8'), + 'total_tire' => '8', + 'load_weight' => $this->input->POST('vdLt8wt') + ); + $i++; + } + if ($this->input->POST('vdLt10')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLt10'), + 'total_tire' => '10', + 'load_weight' => $this->input->POST('vdLt10wt') + ); + $i++; + } + if ($this->input->POST('vdLt12')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLt12'), + 'total_tire' => '12', + 'load_weight' => $this->input->POST('vdLt12wt') + ); + $i++; + } + if ($this->input->POST('vdLt14')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLt14'), + 'total_tire' => '14', + 'load_weight' => $this->input->POST('vdLt14wt') + ); + $i++; + } + if ($this->input->POST('vdLt18')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLt18'), + 'total_tire' => '18', + 'load_weight' => $this->input->POST('vdLt18wt') + ); + $i++; + } + if ($this->input->POST('vdLtot')!='') + { + $datavehicle[$i] = array ( + 'id' => '', + 'id_visit' => '', + 'category' => 'Truck', + 'type' => 'Normal', + 'qty' => $this->input->POST('vdLtot'), + 'total_tire' => '-1', + 'load_weight' => $this->input->POST('vdLtotwt') + ); + $i++; + } + + /* + 'otr1Type' => $this->input->POST('vdQtrType'), + 'otr1Qty' => $this->input->POST('vdQtrQty'), + 'otr1Tyre' => $this->input->POST('vdQtrTyre') + */ + + //purchase + $countpurchase = 0; + $purchase = array ( + 'MRFp' => $this->input->POST('pattern'), + 'MRFs' => $this->input->POST('size'), + 'MRFq' => $this->input->POST('qty'), + 'OTHb' => $this->input->POST('obrand'), + 'OTHp' => $this->input->POST('opattern'), + 'OTHs' => $this->input->POST('osize'), + 'OTHq' => $this->input->POST('oqty') + ); + //$mrfc = $this->input->POST('MRFcount'); + $count = count($purchase['MRFp']); + for ($k = 0 ; $k < $count ; $k++) + { + $datapurchase[$countpurchase] = array ( + 'id' => '', + 'id_visit' => '', + 'brand' => 'MRF', + 'pattern' => $purchase['MRFp'][$k], + 'size' => $purchase['MRFs'][$k], + 'qty' => $purchase['MRFq'][$k] + ); + $countpurchase++; + } + + $count2 = count($purchase['OTHp']); + $v = 0; + for ($n = 0 ; $n < $count2 ; $n++) + { + $datapurchase[$countpurchase] = array ( + 'id' => '', + 'id_visit' => '', + 'brand' => $purchase['OTHb'][$v], + 'pattern' => $purchase['OTHp'][$n], + 'size' => $purchase['OTHs'][$n], + 'qty' => $purchase['OTHq'][$n] + ); + $countpurchase++; + $v++; + } + + //recommendation + + $countrcm = 0; + $recommend = array ( + 'pattern' => $this->input->POST('rpattern'), + 'size' => $this->input->POST('rsize'), + 'remark' => $this->input->POST('rremark') + ); + $count3 = count($recommend['pattern']);; + for ($n = 0 ; $n < $count3 ; $n++) + { + $datarecommended[$countrcm] = array ( + 'id' => '', + 'id_visit' => '', + 'pattern' => $recommend['pattern'][$n], + 'size' => $recommend['size'][$n], + 'remark' => $recommend['remark'][$n], + ); + $countrcm++; + } + + + $data = array( + 'customer' => $datacustomer, + 'visit' => $datavisit, + 'vehicle' => $datavehicle, + 'purchase' => $datapurchase, + 'recommendation' => $datarecommended + ); + //$this->submit_form($data); + echo JSON_ENCODE($data); + } + + //insert + function submit_form($data) + { + //customer + $idc = 4; + $idc = $this->M_form->insertcustomer($data['customer']); + + //visit + $data['visit']['id_customer'] = $idc; + $idv = 3; + $idv = $this->M_form->insertvisit($data['visit']); + + + //vehicle + for ($i=0;$iM_form->insertvehicle($data['vehicle'][$j]); + } + + //purchase + for ($i=0;$iM_form->insertpurchase($data['purchase'][$j]); + } + + //recommendation + for ($i=0;$iM_form->insertrecommended($data['recommendation'][$j]); + } + + $notif = array( + 'status' => '1', + 'tipe' => 'alert-success', + 'message' => 'Well Done | Form is Submitted' + ); + $this->session->set_userdata($notif); + redirect('user','refresh'); + //echo JSON_ENCODE($data); + } + + + function addSellout() + { + $data = array ( + 'id_customer' => $this->input->POST('ID'), + 'customer' => $this->input->POST('customer'), + 'bulan' => $this->input->POST('bulan'), + 'tahun' => $this->input->POST('tahun'), + 'qty' => $this->input->POST('qty') + ); + $this->M_form->newSellout($data); + $notif = array( + 'status' => '1', + 'tipe' => 'alert-success', + 'message' => 'Well Done | Selling out added' + ); + $this->session->set_userdata($notif); + redirect('user','refresh'); + } + + function addVolume() + { + $data = array ( + 'id' => '', + 'dealer' => $this->input->POST('dealer'), + 'area' => $this->input->POST('area'), + 'region' => $this->input->POST('region'), + 'province' => $this->input->POST('province'), + 'date' => $this->input->POST('date'), + 'target' => $this->input->POST('target'), + 'previous_stock'=> $this->input->POST('prevstock'), + 'actual' => $this->input->POST('actual'), + 'sellout' => $this->input->POST('sellout'), + 'order' => $this->input->POST('order'), + 'pattern' => $this->input->POST('pattern') + ); + $data['current_stock'] = $data['previous_stock']+$data['actual']-$data['sellout']; + $pattern = $this->input->POST('pattern'); + if(($pattern== ("7.50-16 M77")) or ($pattern==("7.50-16 SLUG")) or ($pattern==("7.50-16 SM95"))) + { + $data['category'] = 'Light Truck'; + } + else $data['category'] = 'Truck'; + $data['service_level'] = $data['actual'] / $data['order']; + + //echo JSON_ENCODE($data); + $this->M_form->newVolume($data); + + $notif = array( + 'status' => '1', + 'tipe' => 'alert-success', + 'message' => 'Well Done | Volume added' + ); + $this->session->set_userdata($notif); + redirect('user','refresh'); + } + + function loadwilayah() + { + $data = $this->M_form->getwilayah(); + echo JSON_ENCODE($data); + } +} \ No newline at end of file diff --git a/application/controllers/index.html b/application/controllers/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/controllers/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/controllers/user.php b/application/controllers/user.php new file mode 100644 index 0000000..c68761d --- /dev/null +++ b/application/controllers/user.php @@ -0,0 +1,149 @@ +load->model('M_form'); + } + + function index() + { + if($this->auth->CI->session->userdata('is_log_in')) + { + if($this->auth->CI->session->userdata('role')=='Admin') + { + $this->load->view('vAdmin'); + } + else + { + redirect('form'); + } + }else + { + //load halaman login + $this->load->view('vLogin'); + } + $array_items = array('status' => '', 'tipe' => '', 'message' => ''); + $this->session->unset_userdata($array_items); + } + + function loadform() + { + if ($this->cekLogin()) + { + $data['form_saved'] = $this->M_form->getFormSaved(); + $data['form_pending'] = $this->M_form->getFormPending(); + $this->load->view('vAdminForm',$data); + } + else + { + //$this->load->view('vLogin'); + } + } + + function loadstaff() + { + $data['user'] = $this->M_form->getUser(); + $this->load->view('vAdminStaff',$data); + } + + function loadsellingout() + { + $data['sellout'] = $this->M_form->getSellout(); + $this->load->view('vAdminSellingout',$data); + } + + function loadvolume() + { + $data['volume'] = $this->M_form->getVolume(); + $this->load->view('vAdminVolume',$data); + } + + function login_auth() + { + $username = $this->input->post('username'); + $password = $this->input->post('password'); + $success = $this->auth->do_login($username,$password); + if($success) + { + $notif = array( + 'status' => '1', + 'tipe' => 'alert-info', + 'message' => 'Welcome back '.$this->auth->CI->session->userdata('nama') + ); + $this->session->set_userdata($notif); + redirect('user'); + } + else + { + //wrong log in + $data['login_info'] = "Maaf, username dan password salah!"; + $this->load->view('vLogin',$data); + } + } + + function logout() + { + //$this->auth->CI->session->unset_userdata(); + $this->auth->CI->session->sess_destroy(); + redirect('user'); + } + + function insert_user() + { + $datauser = array ( + 'nama' => $this->input->post('nama'), + 'username' => $this->input->post('username'), + 'password' => md5($this->input->post('password')), + 'role' => $this->input->post('role') + ); + $cek = $this->M_form->newuser($datauser); + if ($cek) + { + $notif = array( + 'status' => '1', + 'tipe' => 'alert-success', + 'message' => 'Well Done | Sales baru berhasil diinput' + ); + $this->session->set_userdata($notif); + redirect('user'); + } + else + { + $notif = array( + 'status' => '1', + 'tipe' => 'alert-error', + 'message' => 'Well Done | Sales baru berhasil diinput' + ); + $this->session->set_userdata($notif); + redirect('user'); + } + } + + function delete_user($id) + { + $id = $this->M_form->delete_user($id); + + redirect('user'); + } + + function cekLogin() + { + if($this->auth->CI->session->userdata('is_log_in')) + { + if($this->auth->CI->session->userdata('role')=='Admin') + { + return true; + } + else + { + redirect('Form'); + } + }else + { + //load halaman login + return false; + } + } +} \ No newline at end of file diff --git a/application/core/index.html b/application/core/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/core/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/errors/error_404.php b/application/errors/error_404.php new file mode 100644 index 0000000..792726a --- /dev/null +++ b/application/errors/error_404.php @@ -0,0 +1,62 @@ + + + +404 Page Not Found + + + +
+

+ +
+ + \ No newline at end of file diff --git a/application/errors/error_db.php b/application/errors/error_db.php new file mode 100644 index 0000000..b396cda --- /dev/null +++ b/application/errors/error_db.php @@ -0,0 +1,62 @@ + + + +Database Error + + + +
+

+ +
+ + \ No newline at end of file diff --git a/application/errors/error_general.php b/application/errors/error_general.php new file mode 100644 index 0000000..fd63ce2 --- /dev/null +++ b/application/errors/error_general.php @@ -0,0 +1,62 @@ + + + +Error + + + +
+

+ +
+ + \ No newline at end of file diff --git a/application/errors/error_php.php b/application/errors/error_php.php new file mode 100644 index 0000000..f085c20 --- /dev/null +++ b/application/errors/error_php.php @@ -0,0 +1,10 @@ +
+ +

A PHP Error was encountered

+ +

Severity:

+

Message:

+

Filename:

+

Line Number:

+ +
\ No newline at end of file diff --git a/application/errors/index.html b/application/errors/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/errors/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/helpers/index.html b/application/helpers/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/helpers/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/hooks/index.html b/application/hooks/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/hooks/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/index.html b/application/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/language/english/index.html b/application/language/english/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/language/english/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/libraries/auth.php b/application/libraries/auth.php new file mode 100644 index 0000000..6a9ce24 --- /dev/null +++ b/application/libraries/auth.php @@ -0,0 +1,62 @@ +CI =& get_instance(); + } + // untuk validasi login + function do_login($username,$password) + { + // cek di database, ada ga? + $this->CI->db->from('user'); + $this->CI->db->where('username',$username); + $this->CI->db->where('password=("'.md5($password).'")','',false); + $result = $this->CI->db->get(); + if($result->num_rows() == 0) + { + // username dan password tsb tidak ada + return false; + } + else + { + // ada, maka ambil informasi dari database + $userdata = $result->row(); + if($userdata->role == "admin") $rule = 'Admin'; + else $rule = 'Sales'; + $session_data = array( + 'username' => $userdata->username, + 'nama' => $userdata->nama, + 'role' => $rule, + 'is_log_in' => TRUE + ); + // buat session + $this->CI->session->set_userdata($session_data); + return true; + } + } + // untuk mengecek apakah user sudah login/belum + function is_logged_in() + { + if($this->CI->session->userdata('user_id') == '') + { + return false; + } + return true; + } + // untuk validasi di setiap halaman yang mengharuskan authentikasi + function restrict() + { + if($this->is_logged_in() == false) + { + redirect('home/login'); + } + } +} \ No newline at end of file diff --git a/application/libraries/index.html b/application/libraries/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/libraries/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/logs/index.html b/application/logs/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/logs/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/models/M_form.php b/application/models/M_form.php new file mode 100644 index 0000000..6f46699 --- /dev/null +++ b/application/models/M_form.php @@ -0,0 +1,211 @@ +db->insert('customer',$data); + return $this->db->insert_id(); + } + + function insertvisit($data) + { + $this->db->insert('visit',$data); + return $this->db->insert_id(); + } + + function insertvehicle($data) + { + $this->db->insert('customer_vehicle',$data); + return $this->db->affected_rows(); + } + + function insertrecommended($data) + { + $this->db->insert('recommendation',$data); + return $this->db->affected_rows(); + } + + function insertpurchase($data) + { + $this->db->insert('purchase',$data); + return $this->db->affected_rows(); + } + + function getFormSaved() + { + $query=$this->db->query("SELECT * FROM `visit` WHERE `isApprove` = '1' ORDER BY id DESC"); + return $query->result(); + } + + function getFormPending() + { + $query=$this->db->query("SELECT * FROM `visit` WHERE `isApprove` = '0' ORDER BY id DESC"); + return $query->result(); + } + + function getVisit($id) + { + $q="SELECT * FROM visit WHERE id='$id'"; + $query=$this->db->query($q); + return $query->row(); + } + + function getCust($id) + { + $sql="SELECT * FROM customer WHERE id = (SELECT id_customer FROM visit WHERE id='$id')"; + $query=$this->db->query($sql); + return $query->row(); + } + + function getVehicle($id) + { + $sql="SELECT * FROM customer_vehicle WHERE id_visit='$id'"; + //$query=$this->db->query($q); + $sql = mysql_query($sql); + while ($array = mysql_fetch_assoc($sql)) { + $rs[] = $array; + } + if (empty($rs)) + { + $rs = ''; + } + return $rs; + //return $query->row(); + } + + function getPurchase($id) + { + $sql="SELECT * FROM purchase WHERE id_visit='$id'"; + //$query=$this->db->query($q); + $sql = mysql_query($sql); + while ($array = mysql_fetch_assoc($sql)) { + $rs[] = $array; + } + if (empty($rs)) + { + $rs = ''; + } + return $rs; + //return $query->row(); + } + + function getRecommendation($id) + { + $sql="SELECT * FROM recommendation WHERE id_visit='$id'"; + //$query=$this->db->query($q); + $sql = mysql_query($sql); + while ($array = mysql_fetch_assoc($sql)) { + $rs[] = $array; + } + if (empty($rs)) + { + $rs = ''; + } + return $rs; + //return $query->row(); + } + + function getPictures($id) + { + $sql="SELECT * FROM pictures WHERE id_visit='$id'"; + //$query=$this->db->query($q); + $sql = mysql_query($sql); + while ($array = mysql_fetch_assoc($sql)) { + $rs[] = $array; + } + if (empty($rs)) + { + $rs = ''; + } + return $rs; + } + + function isApprove($data, $id) + { + + $idc = $this->getCustomer($id); + $this->updateCustomer($idc['id_customer'],$data['id_customer']); + $this->db->where('id', $id); + $this->db->update('visit', $data); + } + + function getCustomer($id) + { + $sql="SELECT id_customer FROM visit WHERE id='$id'"; + $sql = mysql_query($sql); + //echo $sql; + $rs = mysql_fetch_assoc($sql); + return $rs; + } + + function updateCustomer($idc,$id) + { + $data = array ( + 'id_customer' => $id + ); + $this->db->where('id', $idc); + $this->db->update('customer', $data); + } + + function searchcustomer($clue) + { + $sql="SELECT id,nama FROM customer WHERE nama like '%$clue%'"; + //$query=$this->db->query($q); + $sql = mysql_query($sql); + while ($array = mysql_fetch_assoc($sql)) { + $rs[] = $array; + } + if (empty($rs)) + { + $rs = ''; + } + return $rs; + } + + function newUser($data) + { + $this->db->insert('user',$data); + return $this->db->affected_rows(); + } + + function getUser() + { + $query=$this->db->query("SELECT * FROM `user`"); + return $query->result(); + } + + function delete_user($id) + { + $query=$this->db->query("DELETE FROM user WHERE username='$id'"); + } + + function getSellout() + { + $query=$this->db->query("SELECT * FROM `sellingout`"); + return $query->result(); + } + + function newSellout($data) + { + $this->db->insert('sellingout',$data); + return $this->db->affected_rows(); + } + + function getVolume() + { + $query=$this->db->query("SELECT * FROM `volume`"); + return $query->result(); + } + + function newVolume($data) + { + $this->db->insert('volume',$data); + return $this->db->affected_rows(); + } + + function getWilayah() + { + $query=$this->db->query("SELECT * FROM `wilayah`"); + return $query->result(); + } +} \ No newline at end of file diff --git a/application/models/index.html b/application/models/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/models/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/third_party/index.html b/application/third_party/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/third_party/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/views/admin/bAdmin.php b/application/views/admin/bAdmin.php new file mode 100644 index 0000000..0999b97 --- /dev/null +++ b/application/views/admin/bAdmin.php @@ -0,0 +1,185 @@ + + +Admin Page + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + session->userdata('status')=='1' ) + { + $tipe = $this->session->userdata('tipe'); + echo " +
+ + ".$this->session->userdata('message')." +
"; + } + ?> + +
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/application/views/bForm.php b/application/views/bForm.php new file mode 100644 index 0000000..2e50538 --- /dev/null +++ b/application/views/bForm.php @@ -0,0 +1,823 @@ + + + + + Form Customer + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + +
+
+
+ Contact Details +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ General Location +
+ + + +
+ Company Details +
+ + + + + +
+ + + +
+ + + +
+ +
+
+
+ Address / Phone no +
+ + + +
+ + + +
+ Contact Person +
+ + + +
+ Nature Business +
+ + + + + +
+ + + +
+
+

+
+
+ Vehicles Details +
+ + + + + + + + + + + + + + + + + + + +
Number of vehicles owned
+ + + + + + + + + + + + + + + + + +
Light TruckQTY
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TruckQTY
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
QTR
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Load and Speed Details
Type of Load
+ + + + + +
+ + + + + +
Average Weight of Loads
+ + + + + + + + + + + + + + + + + +
TruckWt
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Light TrWt
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
Points of Origin Destination
Driving Condition
+
+ + % +
+
+ + % +
+
+
+ + % +
+
+ + % +
+
+
+

+
+
+ Types +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Tyre Brands and Type +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + +
Type of Purchase
+ + + +
Type
+ + + + + + + +
+
+

+
+
+ Tyre Usages +
+
+
+
+ Milleage

+ + + +

+
+ + Km +


+
+ + Km +


+ + +
+
+ New Tyre Purchase per Month

+ + + +

+
+

+
+
+ Front Tyre

+

+ +    + + +
+
+ Rear Tyre

+

+ +    + + +
+


+
+

+ +
+
+
+

+
+
+ Recommendation +
+
+ + + + +
+
+

+
+
+ Upload Picture +
+
+ +

+
+

+ +
+
+
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/views/bHalamanAdmin.php b/application/views/bHalamanAdmin.php new file mode 100644 index 0000000..c7f5096 --- /dev/null +++ b/application/views/bHalamanAdmin.php @@ -0,0 +1,336 @@ + + +Admin Page + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+
+ session->userdata('status')=='1' ) + { + $tipe = $this->session->userdata('tipe'); + echo " +
+ + ".$this->session->userdata('message')." +
"; + } + ?> +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Date/Time Sender Area Customer/Client Action
2013-05-27 16:25:39MarkJawa TengahOmdo +
date; ?>sender; ?>area; ?>customer; ?> + +
+
+
+ Tambah +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Date/Time Sender Area Customer/Client Action
1MarkJawa TengahOmdo + +
date; ?>sender; ?>area; ?>customer; ?> + +
+
+
+
+
+
+ +
+
+ Tambah + +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Name Username Role Action
MarkMarkJawa Tengah + +
nama; ?>username; ?>role; ?> + +
+
+
+
+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/application/views/bReview.php b/application/views/bReview.php new file mode 100644 index 0000000..a76bc7a --- /dev/null +++ b/application/views/bReview.php @@ -0,0 +1,828 @@ + + + + + Form Customer + + + + + + + + + + nature_bisnis); + $onature = end($nature_bisnis); // move the internal pointer to the end of the array + //$onature = key($nature_bisnis); + ?> + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ Contact Details +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ General Location +
+
+ + +
+
+
+ + +
+
+ Company Details +
+ + + + + +
+
+ + +
+
+
+ + +
+
+ + + +
+ +
+
+
+ Address / Phone no +
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+ Contact Person +
+
+ + +
+
+
+ + +
+
+ Nature Business +
+ + + + + +
+ + + +
+
+

+
+
+ Vehicles Details +
+ + + + + + + + + + + + + + + + + + + +
Number of vehicles owned
+ + + + + + + + + + + + + + + + + +
Light TruckQTY
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TruckQTY
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
QTR
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Load and Speed Details
Type of Load
+ + + + + +
+ + + + + +
Average Weight of Loads
+ + + + + + + + + + + + + + + + + +
TruckWt
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Light TrWt
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
Points of Origin Destination
Driving Condition
+
+ + + % +
+
+ + + % +
+
+
+ + + % +
+
+ + + % +
+
+
+

+
+
+ Types +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Tyre Brands and Type +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + +
Type of Purchase
+ + + +
Type
+ + + + + + + +
+
+

+
+
+ Tyre Usages +
+
+
+
+ Milleage

+ + + +

+
+ + Km +


+
+ + Km +


+ + +
+
+ New Tyre Purchase per Month

+ + + +

+
+

+
+
+ Front Tyre

+ +

+ +    + + +
+
+ Rear Tyre

+ +

+ +    + + +
+


+
+ +

+ +
+
+
+

+
+
+ Recommendation +
+
+

+
+
+ Picture +
+ +
+ + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/application/views/index.html b/application/views/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/application/views/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + \ No newline at end of file diff --git a/application/views/vAdmin.php b/application/views/vAdmin.php new file mode 100644 index 0000000..09fa3f5 --- /dev/null +++ b/application/views/vAdmin.php @@ -0,0 +1,163 @@ + + +Admin Page + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + session->userdata('status')=='1' ) + { + $tipe = $this->session->userdata('tipe'); + echo " +
+ + ".$this->session->userdata('message')." +
"; + } + ?> + +
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/application/views/vAdminForm.php b/application/views/vAdminForm.php new file mode 100644 index 0000000..db0099c --- /dev/null +++ b/application/views/vAdminForm.php @@ -0,0 +1,94 @@ + +
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Date/Time Sender Area Customer/Client Action
2013-05-27 16:25:39MarkJawa TengahSuprapto +
date_visit; ?>sender; ?>province; ?>customer; ?> + +
+
+
+ Tambah +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Date/Time Sender Area Customer/Client Action
2013-07-25 15:28:56MarkJawa TengahSumartoyo + +
date_visit; ?>sender; ?>province; ?>customer; ?> + +
+
+
\ No newline at end of file diff --git a/application/views/vAdminSellingout.php b/application/views/vAdminSellingout.php new file mode 100644 index 0000000..3740759 --- /dev/null +++ b/application/views/vAdminSellingout.php @@ -0,0 +1,178 @@ + +
+ +
+
+ Tambah +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Customer Date Quantity Action
everseikoJanuary 20135 + + +
customer; ?>bulan." ".$so->tahun; ?>qty; ?> + + +
+
+ + + \ No newline at end of file diff --git a/application/views/vAdminStaff.php b/application/views/vAdminStaff.php new file mode 100644 index 0000000..2a0b112 --- /dev/null +++ b/application/views/vAdminStaff.php @@ -0,0 +1,94 @@ + +
+ +
+
+ Tambah +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Name Username Role Action
MarkMarkJawa Tengah + +
nama; ?>username; ?>role; ?> + +
+
+ + + + \ No newline at end of file diff --git a/application/views/vAdminVolume.php b/application/views/vAdminVolume.php new file mode 100644 index 0000000..cb32882 --- /dev/null +++ b/application/views/vAdminVolume.php @@ -0,0 +1,226 @@ + +
+ +
+
+ Tambah +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Dealaer Region Province Area Month Target Sellout Order Previous Stock Actual Current Stock Category Pattern Service Level
everseikoJawaJawa BaratBandungApril462775
dealer; ?>region; ?>province; ?>area; ?>date; ?>target; ?>sellout; ?>order; ?>previous_stock; ?>actual; ?>current_stock; ?>category; ?>pattern; ?>service_level; ?>
+
+ + + + \ No newline at end of file diff --git a/application/views/vForm2.php b/application/views/vForm2.php new file mode 100644 index 0000000..42bd8e5 --- /dev/null +++ b/application/views/vForm2.php @@ -0,0 +1,924 @@ + + + + + Form Customer + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ session->userdata('status')=='1' ) + { + $tipe = $this->session->userdata('tipe'); + echo " +
+ + ".$this->session->userdata('message')." +
"; + } + ?> + +
+
+
+
+
+ +
+ Contact Details + +
General Location
+ + + +
Company Details
+ + + +

+ + + +

+ + +

+ + +
Address / Phone no
+ + +

+ + +

+
Contact Person
+ + +

+
Nature Business
+ + + + + + + +
+ +
+
+ Vehicles Details + + + + + + + + + + + + + + + +
Number of vehicles owned
+ + + + + + + + + + + + + + + + + +
Light TruckQTY
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TruckQTY
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
QTR
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Load and Speed Details
Type of Load
+ + + + + +
+ + + + + +
Average Weight of Loads
+ + + + + + + + + + + + + + + + + +
Light TruckWt
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TruckWt
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
Points of Origin Destination
Driving Condition
+
+ + % +
+
+ + % +
+
+
+ + % +
+
+ + % +
+
+
+
+ +
+ Types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Tyre Brands and Type +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + +
Type of Purchase
+ + + +
Type
+ + + + + + + +
+
+ +
+ Tyre Usages +
+
+
+ Milleage

+ + +

+
+ + Km +


+
+ + Km +


+ + +
+
+ New Tyre Purchase per Month

+ + +

+ + +
+
+ + + + +
+
+ +
+
+
+ + + + + +
+
+ +

+
+

+
+
+ Front Tyre

+

+    + +
+
+ Rear Tyre

+

+    + +
+


+
+

+ +
+
+
+ +
+ Recommendation +
+
+ + + + +
+ +
+ +
+ + + +
+
+ + + +
+
+
+ +
+ Upload Picture +
+ +

+
+
+

+ +
+
+ +
+ Confirm +
+

+ +

+
+
+
+
+
+
+
+ + +
+
+ +
+ +
+

© Everseiko 2013

+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/application/views/vLogin.php b/application/views/vLogin.php new file mode 100644 index 0000000..d83b22d --- /dev/null +++ b/application/views/vLogin.php @@ -0,0 +1,81 @@ + + + +Login + + + + + + + + + + + +
+ +
'; + } + ?> +
Login
+ + + + + + + + + + + \ No newline at end of file diff --git a/application/views/vReview.php b/application/views/vReview.php new file mode 100644 index 0000000..b5beed2 --- /dev/null +++ b/application/views/vReview.php @@ -0,0 +1,920 @@ + + + + + + Form Customer + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+
+ Contact Details +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
General Location
+
+ + +
+
+
+ + +
+
Company Details
+ + + + + +
+
+ + +
+
+
+ + +
+
+ + + +
+
+
Address / Phone no
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
Contact Person
+
+ + +
+
+
+ + +
+
Nature Business
+ + + + + +
+ + + + + +
+ +
+
+

+
+
+ Vehicles Details +
+ + + + + + + + + + + +
Number of vehicles owned
+ + + + + + + + + + + + + + + + + +
Lt TruckQTY
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TruckQTY
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
OTR
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Load and Speed Details
Type of Load
+ + + + + +
+ + + + + +
Average Weight of Loads
+ + + + + + + + + + + + + + + + + +
Lt TruckWt
4 wheels + +
6 wheels + +
10 wheels + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TruckWt
6 wheels + +
8 wheels + +
10 wheels + +
12 wheels + +
14 wheels + +
18 wheels + +
Other + +
+
Points of Origin Destination
Driving Condition
+
+ + + % +
+
+ + + % +
+
+
+ + + % +
+
+ + + % +
+
+
+

+
+
+ Types +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tyre Brands and Type
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + +
Type of Purchase
+ + + +
Type
+ + + + + + + +
+ +
+
+

+
+
+ Tyre Usages +
+
+
+
+ Milleage

+ + +

+
+ + Km +
+

+
+ + Km +


+ + + +
+
+ New Tyre Purchase per Month

+ + + + + + + + + + + + + + + + + +
Brand + +
MRF +
+ +
+
+ + +
Other +
+ +
+
+ + +
+

+
+
+
+
+
+ Front Tyre

+ +

+ +    + + +
+
+ Rear Tyre

+ +

+ +    + + +
+


+
+ +

+ +
+
+
+

+
+
+ Recommendation +
+
+ Pattern                           +     Size                 +                   Remark +
+
+
No Recommendation Available
+
+








+
+

+
+
+ Picture +
+
+ +
+ + + +
+ +
+
+ + + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/asset/bootstrap/css/bootstrap-responsive.css b/asset/bootstrap/css/bootstrap-responsive.css new file mode 100644 index 0000000..09e88ce --- /dev/null +++ b/asset/bootstrap/css/bootstrap-responsive.css @@ -0,0 +1,1109 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +@-ms-viewport { + width: device-width; +} + +.hidden { + display: none; + visibility: hidden; +} + +.visible-phone { + display: none !important; +} + +.visible-tablet { + display: none !important; +} + +.hidden-desktop { + display: none !important; +} + +.visible-desktop { + display: inherit !important; +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important ; + } + .visible-tablet { + display: inherit !important; + } + .hidden-tablet { + display: none !important; + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important; + } + .visible-phone { + display: inherit !important; + } + .hidden-phone { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: inherit !important; + } + .hidden-print { + display: none !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + .span12 { + width: 1170px; + } + .span11 { + width: 1070px; + } + .span10 { + width: 970px; + } + .span9 { + width: 870px; + } + .span8 { + width: 770px; + } + .span7 { + width: 670px; + } + .span6 { + width: 570px; + } + .span5 { + width: 470px; + } + .span4 { + width: 370px; + } + .span3 { + width: 270px; + } + .span2 { + width: 170px; + } + .span1 { + width: 70px; + } + .offset12 { + margin-left: 1230px; + } + .offset11 { + margin-left: 1130px; + } + .offset10 { + margin-left: 1030px; + } + .offset9 { + margin-left: 930px; + } + .offset8 { + margin-left: 830px; + } + .offset7 { + margin-left: 730px; + } + .offset6 { + margin-left: 630px; + } + .offset5 { + margin-left: 530px; + } + .offset4 { + margin-left: 430px; + } + .offset3 { + margin-left: 330px; + } + .offset2 { + margin-left: 230px; + } + .offset1 { + margin-left: 130px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975%; + } + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212%; + } + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266%; + } + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411%; + } + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556%; + } + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014%; + } + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847%; + } + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924%; + } + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375%; + } + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828%; + } + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281%; + } + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171%; + } + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915%; + } + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316%; + } + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061%; + } + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462%; + } + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206%; + } + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607%; + } + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352%; + } + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753%; + } + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497%; + } + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899%; + } + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642%; + } + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444%; + } + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875%; + } + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219%; + } + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933%; + } + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354%; + } + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785%; + } + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048%; + } + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224%; + } + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257%; + } + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369%; + } + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708%; + } + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + .thumbnails { + margin-left: -30px; + } + .thumbnails > li { + margin-left: 30px; + } + .row-fluid .thumbnails { + margin-left: 0; + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + .span12 { + width: 724px; + } + .span11 { + width: 662px; + } + .span10 { + width: 600px; + } + .span9 { + width: 538px; + } + .span8 { + width: 476px; + } + .span7 { + width: 414px; + } + .span6 { + width: 352px; + } + .span5 { + width: 290px; + } + .span4 { + width: 228px; + } + .span3 { + width: 166px; + } + .span2 { + width: 104px; + } + .span1 { + width: 42px; + } + .offset12 { + margin-left: 764px; + } + .offset11 { + margin-left: 702px; + } + .offset10 { + margin-left: 640px; + } + .offset9 { + margin-left: 578px; + } + .offset8 { + margin-left: 516px; + } + .offset7 { + margin-left: 454px; + } + .offset6 { + margin-left: 392px; + } + .offset5 { + margin-left: 330px; + } + .offset4 { + margin-left: 268px; + } + .offset3 { + margin-left: 206px; + } + .offset2 { + margin-left: 144px; + } + .offset1 { + margin-left: 82px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608%; + } + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387%; + } + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166%; + } + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946%; + } + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725%; + } + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504%; + } + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283%; + } + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062%; + } + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841%; + } + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199%; + } + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988%; + } + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962%; + } + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031%; + } + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274%; + } + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089%; + } + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252%; + } + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868%; + } + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299%; + } + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647%; + } + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079%; + } + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427%; + } + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584%; + } + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065%; + } + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376%; + } + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986%; + } + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417%; + } + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765%; + } + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196%; + } + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544%; + } + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746%; + } + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227%; + } + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537%; + } + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102%; + } + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325%; + } + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px; + } + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-right: -20px; + margin-left: -20px; + } + .container-fluid { + padding: 0; + } + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left; + } + .dl-horizontal dd { + margin-left: 0; + } + .container { + width: auto; + } + .row-fluid { + width: 100%; + } + .row, + .thumbnails { + margin-left: 0; + } + .thumbnails > li { + float: none; + margin-left: 0; + } + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0; + } + .modal.fade { + top: -100px; + } + .modal.fade.in { + top: 20px; + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + .page-header h1 small { + display: block; + line-height: 20px; + } + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + .form-horizontal .controls { + margin-left: 0; + } + .form-horizontal .control-list { + padding-top: 0; + } + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px; + } + .media .pull-left, + .media .pull-right { + display: block; + float: none; + margin-bottom: 10px; + } + .media-object { + margin-right: 0; + margin-left: 0; + } + .modal { + top: 10px; + right: 10px; + left: 10px; + } + .modal-header .close { + padding: 10px; + margin: -10px; + } + .carousel-caption { + position: static; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + .navbar-fixed-top { + margin-bottom: 20px; + } + .navbar-fixed-bottom { + margin-top: 20px; + } + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + .navbar .container { + width: auto; + padding: 0; + } + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px; + } + .nav-collapse { + clear: both; + } + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + .nav-collapse .nav > li { + float: none; + } + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + .nav-collapse .nav > .divider-vertical { + display: none; + } + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + .nav-collapse .nav > li > a:hover, + .nav-collapse .nav > li > a:focus, + .nav-collapse .dropdown-menu a:hover, + .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2; + } + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .nav > li > a:focus, + .navbar-inverse .nav-collapse .dropdown-menu a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111111; + } + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px; + } + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .nav-collapse .open > .dropdown-menu { + display: block; + } + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + .nav-collapse .dropdown-menu .divider { + display: none; + } + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + .nav-collapse, + .nav-collapse.collapse { + height: 0; + overflow: hidden; + } + .navbar .btn-navbar { + display: block; + } + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} diff --git a/asset/bootstrap/css/bootstrap-responsive.min.css b/asset/bootstrap/css/bootstrap-responsive.min.css new file mode 100644 index 0000000..f4ede63 --- /dev/null +++ b/asset/bootstrap/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/asset/bootstrap/css/bootstrap.css b/asset/bootstrap/css/bootstrap.css new file mode 100644 index 0000000..43dc567 --- /dev/null +++ b/asset/bootstrap/css/bootstrap.css @@ -0,0 +1,6194 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img, +.google-maps img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover, +a:focus { + color: #005580; + text-decoration: underline; +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + line-height: 0; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} + +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.127659574468085%; +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594%; +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361%; +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126%; +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893%; +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659%; +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425%; +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192%; +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576%; +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233%; +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894%; +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553%; +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275%; +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467%; +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404%; +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232%; +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807%; +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999%; +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572%; +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764%; +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339%; +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553%; +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106%; +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297%; +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715%; +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063%; +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638%; +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383%; +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405%; +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596%; +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617%; +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618%; +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936%; +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278%; +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702%; +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938%; +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + line-height: 0; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} + +small { + font-size: 85%; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +cite { + font-style: normal; +} + +.muted { + color: #999999; +} + +a.muted:hover, +a.muted:focus { + color: #808080; +} + +.text-warning { + color: #c09853; +} + +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c; +} + +.text-error { + color: #b94a48; +} + +a.text-error:hover, +a.text-error:focus { + color: #953b39; +} + +.text-info { + color: #3a87ad; +} + +a.text-info:hover, +a.text-info:focus { + color: #2d6987; +} + +.text-success { + color: #468847; +} + +a.text-success:hover, +a.text-success:focus { + color: #356635; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + line-height: 40px; +} + +h1 { + font-size: 38.5px; +} + +h2 { + font-size: 31.5px; +} + +h3 { + font-size: 24.5px; +} + +h4 { + font-size: 17.5px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 11.9px; +} + +h1 small { + font-size: 24.5px; +} + +h2 small { + font-size: 17.5px; +} + +h3 small { + font-size: 14px; +} + +h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + padding: 0; + margin: 0 0 10px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +li { + line-height: 20px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +ul.inline, +ol.inline { + margin-left: 0; + list-style: none; +} + +ul.inline > li, +ol.inline > li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 10px; +} + +.dl-horizontal { + *zoom: 1; +} + +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + line-height: 0; + content: ""; +} + +.dl-horizontal:after { + clear: both; +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 180px; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote small { + display: block; + line-height: 20px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 20px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 15px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +input, +textarea, +.uneditable-input { + width: 206px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal; +} + +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +select, +input[type="file"] { + height: 30px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 30px; +} + +select { + width: 220px; + background-color: #ffffff; + border: 1px solid #cccccc; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.uneditable-input, +.uneditable-textarea { + color: #999999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} + +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px; +} + +.controls-row { + *zoom: 1; +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: ""; +} + +.controls-row:after { + clear: both; +} + +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left; +} + +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; +} + +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; +} + +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; +} + +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad; +} + +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad; +} + +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; +} + +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad; +} + +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + line-height: 0; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.help-block, +.help-inline { + color: #595959; +} + +.help-block { + display: block; + margin-bottom: 10px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2; +} + +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group > .dropdown-toggle, +.input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input + .btn-group .btn:last-child, +.input-append select + .btn-group .btn:last-child, +.input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append input + .btn-group .btn, +.input-prepend.input-append select + .btn-group .btn, +.input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0; +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +/* Allow for input prepend/append in search forms */ + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 10px; +} + +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + line-height: 0; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 180px; +} + +.form-horizontal .help-block { + margin-bottom: 0; +} + +.form-horizontal input + .help-block, +.form-horizontal select + .help-block, +.form-horizontal textarea + .help-block, +.form-horizontal .uneditable-input + .help-block, +.form-horizontal .input-prepend + .help-block, +.form-horizontal .input-append + .help-block { + margin-top: 10px; +} + +.form-horizontal .form-actions { + padding-left: 180px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child > th:first-child, +.table-bordered tbody:first-child tr:first-child > td:first-child, +.table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child > th:last-child, +.table-bordered tbody:first-child tr:first-child > td:last-child, +.table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:first-child, +.table-bordered tbody:last-child tr:last-child > td:first-child, +.table-bordered tbody:last-child tr:last-child > th:first-child, +.table-bordered tfoot:last-child tr:last-child > td:first-child, +.table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:last-child, +.table-bordered tbody:last-child tr:last-child > td:last-child, +.table-bordered tbody:last-child tr:last-child > th:last-child, +.table-bordered tfoot:last-child tr:last-child > td:last-child, +.table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0; +} + +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-striped tbody > tr:nth-child(odd) > td, +.table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover tbody tr:hover > td, +.table-hover tbody tr:hover > th { + background-color: #f5f5f5; +} + +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0; +} + +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0; +} + +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0; +} + +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0; +} + +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0; +} + +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0; +} + +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0; +} + +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0; +} + +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0; +} + +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0; +} + +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0; +} + +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0; +} + +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0; +} + +.table tbody tr.success > td { + background-color: #dff0d8; +} + +.table tbody tr.error > td { + background-color: #f2dede; +} + +.table tbody tr.warning > td { + background-color: #fcf8e3; +} + +.table tbody tr.info > td { + background-color: #d9edf7; +} + +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6; +} + +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc; +} + +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc; +} + +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +/* White icons with optional class, or on hover/focus/active states of certain elements */ + +.icon-white, +.nav-pills > .active > a > [class^="icon-"], +.nav-pills > .active > a > [class*=" icon-"], +.nav-list > .active > a > [class^="icon-"], +.nav-list > .active > a > [class*=" icon-"], +.navbar-inverse .nav > .active > a > [class^="icon-"], +.navbar-inverse .nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:focus > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > li > a:focus > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:focus > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"], +.dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + width: 16px; + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px; +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-submenu:hover > a, +.dropdown-submenu:focus > a { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} + +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0; +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #cccccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " "; +} + +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px; +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -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); +} + +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px; +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} + +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn-primary { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #0044cc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #003399 \9; +} + +.btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #ffffff; + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #ffffff; + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #ffffff; + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #ffffff; + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222222; + background-image: -moz-linear-gradient(top, #444444, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #ffffff; + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-link { + color: #0088cc; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333333; + text-decoration: none; +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn + .btn { + margin-left: -1px; +} + +.btn-group > .btn, +.btn-group > .dropdown-menu, +.btn-group > .popover { + font-size: 14px; +} + +.btn-group > .btn-mini { + font-size: 10.5px; +} + +.btn-group > .btn-small { + font-size: 11.9px; +} + +.btn-group > .btn-large { + font-size: 17.5px; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px; +} + +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0044cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 8px; + margin-left: 0; +} + +.btn-large .caret { + margin-top: 6px; +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px; +} + +.dropup .btn-large .caret { + border-bottom-width: 5px; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group-vertical > .btn + .btn { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert, +.alert h4 { + color: #c09853; +} + +.alert h4 { + margin: 0; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success h4 { + color: #468847; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger h4, +.alert-error h4 { + color: #b94a48; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info h4 { + color: #3a87ad; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li > a > img { + max-width: none; +} + +.nav > .pull-right { + float: right; +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover, +.nav-list > .active > a:focus { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + line-height: 0; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover, +.nav-tabs > .active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover, +.nav-pills > .active > a:focus { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.nav-tabs.nav-stacked > li > a:hover, +.nav-tabs.nav-stacked > li > a:focus { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +/* move down carets for tabs */ + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.nav > .dropdown.active > a:hover, +.nav > .dropdown.active > a:focus { + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover, +.nav > li.dropdown.open.active > a:focus { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover, +.tabs-stacked .open > a:focus { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + line-height: 0; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover, +.tabs-below > .nav-tabs > li > a:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover, +.tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover, +.tabs-left > .nav-tabs > li > a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover, +.tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover, +.tabs-right > .nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover, +.tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover, +.nav > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); +} + +.navbar-inner:before, +.navbar-inner:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-inner:after { + clear: both; +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; + overflow: visible; +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777777; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none; +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} + +.navbar-link { + color: #777777; +} + +.navbar-link:hover, +.navbar-link:focus { + color: #333333; +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #ffffff; + border-left: 1px solid #f2f2f2; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.navbar-static-top { + position: static; + margin-bottom: 0; +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px; +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0; +} + +.navbar .nav > li { + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777777; + text-decoration: none; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; +} + +.navbar .nav > li > a:focus, +.navbar .nav > li > a:hover { + color: #333333; + text-decoration: none; + background-color: transparent; +} + +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #cccccc \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .nav > li > .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .nav > li > .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown > a:hover .caret, +.navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555555; + background-color: #e5e5e5; +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #ffffff; +} + +.navbar-inverse .brand { + color: #999999; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #ffffff; +} + +.navbar-inverse .divider-vertical { + border-right-color: #222222; + border-left-color: #111111; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .nav li.dropdown > a:hover .caret, +.navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + margin: 20px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination ul > li { + display: inline; +} + +.pagination ul > li > a, +.pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + border-left-width: 0; +} + +.pagination ul > li > a:hover, +.pagination ul > li > a:focus, +.pagination ul > .active > a, +.pagination ul > .active > span { + background-color: #f5f5f5; +} + +.pagination ul > .active > a, +.pagination ul > .active > span { + color: #999999; + cursor: default; +} + +.pagination ul > .disabled > span, +.pagination ul > .disabled > a, +.pagination ul > .disabled > a:hover, +.pagination ul > .disabled > a:focus { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination ul > li:first-child > a, +.pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.pagination ul > li:last-child > a, +.pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pagination-large ul > li > a, +.pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px; +} + +.pagination-large ul > li:first-child > a, +.pagination-large ul > li:first-child > span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.pagination-large ul > li:last-child > a, +.pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.pagination-mini ul > li:first-child > a, +.pagination-small ul > li:first-child > a, +.pagination-mini ul > li:first-child > span, +.pagination-small ul > li:first-child > span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px; +} + +.pagination-mini ul > li:last-child > a, +.pagination-small ul > li:last-child > a, +.pagination-mini ul > li:last-child > span, +.pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; +} + +.pagination-small ul > li > a, +.pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px; +} + +.pagination-mini ul > li > a, +.pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px; +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + line-height: 0; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.popover-title:empty { + display: none; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + line-height: 0; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #555555; +} + +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + margin-left: 0; + list-style: none; +} + +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +.label:empty, +.badge:empty { + display: none; +} + +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} + +.btn-mini .label, +.btn-mini .badge { + top: 0; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); +} + +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); +} + +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); +} + +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); +} + +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 20px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none; +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + line-height: 20px; + color: #ffffff; +} + +.carousel-caption h4 { + margin: 0 0 5px; +} + +.carousel-caption p { + margin-bottom: 0; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit li { + line-height: 30px; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} + +.affix { + position: fixed; +} + +/* Let's get this party started */ + ::-webkit-scrollbar { + width: 8px; + -webkit-appearance: none; + } + ::-webkit-scrollbar:horizontal { + height: 8px; + } + + /* Track */ + ::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 6px #888888 ; + -webkit-border-radius: 10px; + border-radius: 10px; + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + -webkit-border-radius: 10px; + border-radius: 10px; + background: #888888 ; + -webkit-box-shadow: inset 0 0 6px #C0C0C0; + } + ::-webkit-scrollbar-thumb:window-inactive { + background: #C0C0C0; + } diff --git a/asset/bootstrap/css/bootstrap.min.css b/asset/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..b6428e6 --- /dev/null +++ b/asset/bootstrap/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-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)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/asset/bootstrap/css/docs.css b/asset/bootstrap/css/docs.css new file mode 100644 index 0000000..af65540 --- /dev/null +++ b/asset/bootstrap/css/docs.css @@ -0,0 +1,1067 @@ +/* Add additional stylesheets below +-------------------------------------------------- */ +/* + Bootstrap's documentation styles + Special styles for presenting Bootstrap's documentation and examples +*/ + + + +/* Body and structure +-------------------------------------------------- */ + +body { + position: relative; + padding-top: 40px; +} + +/* Code in headings */ +h3 code { + font-size: 14px; + font-weight: normal; +} + + + +/* Tweak navbar brand link to be super sleek +-------------------------------------------------- */ + +body > .navbar { + font-size: 13px; +} + +/* Change the docs' brand */ +body > .navbar .brand { + padding-right: 0; + padding-left: 0; + margin-left: 20px; + float: right; + font-weight: bold; + color: #000; + text-shadow: 0 1px 0 rgba(255,255,255,.1), 0 0 30px rgba(255,255,255,.125); + -webkit-transition: all .2s linear; + -moz-transition: all .2s linear; + transition: all .2s linear; +} +body > .navbar .brand:hover { + text-decoration: none; + text-shadow: 0 1px 0 rgba(255,255,255,.1), 0 0 30px rgba(255,255,255,.4); +} + + +/* Sections +-------------------------------------------------- */ + +/* padding for in-page bookmarks and fixed navbar */ +section { + padding-top: 30px; +} +section > .page-header, +section > .lead { + color: #5a5a5a; +} +section > ul li { + margin-bottom: 5px; +} + +/* Separators (hr) */ +.bs-docs-separator { + margin: 40px 0 39px; +} + +/* Faded out hr */ +hr.soften { + height: 1px; + margin: 70px 0; + background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0)); + border: 0; +} + + + +/* Jumbotrons +-------------------------------------------------- */ + +/* Base class +------------------------- */ +.jumbotron { + position: relative; + padding: 40px 0; + color: #fff; + text-align: center; + text-shadow: 0 1px 3px rgba(0,0,0,.4), 0 0 30px rgba(0,0,0,.075); + background: #020031; /* Old browsers */ + background: -moz-linear-gradient(45deg, #020031 0%, #6d3353 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left bottom, right top, color-stop(0%,#020031), color-stop(100%,#6d3353)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(45deg, #020031 0%,#6d3353 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(45deg, #020031 0%,#6d3353 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(45deg, #020031 0%,#6d3353 100%); /* IE10+ */ + background: linear-gradient(45deg, #020031 0%,#6d3353 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#020031', endColorstr='#6d3353',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ + -webkit-box-shadow: inset 0 3px 7px rgba(0,0,0,.2), inset 0 -3px 7px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 3px 7px rgba(0,0,0,.2), inset 0 -3px 7px rgba(0,0,0,.2); + box-shadow: inset 0 3px 7px rgba(0,0,0,.2), inset 0 -3px 7px rgba(0,0,0,.2); +} +.jumbotron h1 { + font-size: 80px; + font-weight: bold; + letter-spacing: -1px; + line-height: 1; +} +.jumbotron p { + font-size: 24px; + font-weight: 300; + line-height: 1.25; + margin-bottom: 30px; +} + +/* Link styles (used on .masthead-links as well) */ +.jumbotron a { + color: #fff; + color: rgba(255,255,255,.5); + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.jumbotron a:hover { + color: #fff; + text-shadow: 0 0 10px rgba(255,255,255,.25); +} + +/* Download button */ +.masthead .btn { + padding: 19px 24px; + font-size: 24px; + font-weight: 200; + color: #fff; /* redeclare to override the `.jumbotron a` */ + border: 0; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); + box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); + -webkit-transition: none; + -moz-transition: none; + transition: none; +} +.masthead .btn:hover { + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); + box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); +} +.masthead .btn:active { + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.1); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.1); + box-shadow: inset 0 2px 4px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.1); +} + + +/* Pattern overlay +------------------------- */ +.jumbotron .container { + position: relative; + z-index: 2; +} +.jumbotron:after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: url(../img/bs-docs-masthead-pattern.png) repeat center center; + opacity: .4; +} +@media +only screen and (-webkit-min-device-pixel-ratio: 2), +only screen and ( min--moz-device-pixel-ratio: 2), +only screen and ( -o-min-device-pixel-ratio: 2/1) { + + .jumbotron:after { + background-size: 150px 150px; + } + +} + +/* Masthead (docs home) +------------------------- */ +.masthead { + padding: 70px 0 80px; + margin-bottom: 0; + color: #fff; +} +.masthead h1 { + font-size: 120px; + line-height: 1; + letter-spacing: -2px; +} +.masthead p { + font-size: 40px; + font-weight: 200; + line-height: 1.25; +} + +/* Textual links in masthead */ +.masthead-links { + margin: 0; + list-style: none; +} +.masthead-links li { + display: inline; + padding: 0 10px; + color: rgba(255,255,255,.25); +} + +/* Social proof buttons from GitHub & Twitter */ +.bs-docs-social { + padding: 15px 0; + text-align: center; + background-color: #f5f5f5; + border-top: 1px solid #fff; + border-bottom: 1px solid #ddd; +} + +/* Quick links on Home */ +.bs-docs-social-buttons { + margin-left: 0; + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.bs-docs-social-buttons li { + display: inline-block; + padding: 5px 8px; + line-height: 1; + *display: inline; + *zoom: 1; +} + +/* Subhead (other pages) +------------------------- */ +.subhead { + text-align: left; + border-bottom: 1px solid #ddd; +} +.subhead h1 { + font-size: 60px; +} +.subhead p { + margin-bottom: 20px; +} +.subhead .navbar { + display: none; +} + + + +/* Marketing section of Overview +-------------------------------------------------- */ + +.marketing { + text-align: center; + color: #5a5a5a; +} +.marketing h1 { + margin: 60px 0 10px; + font-size: 60px; + font-weight: 200; + line-height: 1; + letter-spacing: -1px; +} +.marketing h2 { + font-weight: 200; + margin-bottom: 5px; +} +.marketing p { + font-size: 16px; + line-height: 1.5; +} +.marketing .marketing-byline { + margin-bottom: 40px; + font-size: 20px; + font-weight: 300; + line-height: 1.25; + color: #999; +} +.marketing-img { + display: block; + margin: 0 auto 30px; + max-height: 145px; +} + + + +/* Footer +-------------------------------------------------- */ + +.footer { + text-align: center; + padding: 30px 0; + margin-top: 70px; + border-top: 1px solid #e5e5e5; + background-color: #f5f5f5; +} +.footer p { + margin-bottom: 0; + color: #777; +} +.footer-links { + margin: 10px 0; +} +.footer-links li { + display: inline; + padding: 0 2px; +} +.footer-links li:first-child { + padding-left: 0; +} + + + +/* Special grid styles +-------------------------------------------------- */ + +.show-grid { + margin-top: 10px; + margin-bottom: 20px; +} +.show-grid [class*="span"] { + background-color: #eee; + text-align: center; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + min-height: 40px; + line-height: 40px; +} +.show-grid [class*="span"]:hover { + background-color: #ddd; +} +.show-grid .show-grid { + margin-top: 0; + margin-bottom: 0; +} +.show-grid .show-grid [class*="span"] { + margin-top: 5px; +} +.show-grid [class*="span"] [class*="span"] { + background-color: #ccc; +} +.show-grid [class*="span"] [class*="span"] [class*="span"] { + background-color: #999; +} + + + +/* Mini layout previews +-------------------------------------------------- */ +.mini-layout { + border: 1px solid #ddd; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.075); + -moz-box-shadow: 0 1px 2px rgba(0,0,0,.075); + box-shadow: 0 1px 2px rgba(0,0,0,.075); +} +.mini-layout, +.mini-layout .mini-layout-body, +.mini-layout.fluid .mini-layout-sidebar { + height: 300px; +} +.mini-layout { + margin-bottom: 20px; + padding: 9px; +} +.mini-layout div { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.mini-layout .mini-layout-body { + background-color: #dceaf4; + margin: 0 auto; + width: 70%; +} +.mini-layout.fluid .mini-layout-sidebar, +.mini-layout.fluid .mini-layout-header, +.mini-layout.fluid .mini-layout-body { + float: left; +} +.mini-layout.fluid .mini-layout-sidebar { + background-color: #bbd8e9; + width: 20%; +} +.mini-layout.fluid .mini-layout-body { + width: 77.5%; + margin-left: 2.5%; +} + + + +/* Download page +-------------------------------------------------- */ + +.download .page-header { + margin-top: 36px; +} +.page-header .toggle-all { + margin-top: 5px; +} + +/* Space out h3s when following a section */ +.download h3 { + margin-bottom: 5px; +} +.download-builder input + h3, +.download-builder .checkbox + h3 { + margin-top: 9px; +} + +/* Fields for variables */ +.download-builder input[type=text] { + margin-bottom: 9px; + font-family: Menlo, Monaco, "Courier New", monospace; + font-size: 12px; + color: #d14; +} +.download-builder input[type=text]:focus { + background-color: #fff; +} + +/* Custom, larger checkbox labels */ +.download .checkbox { + padding: 6px 10px 6px 25px; + font-size: 13px; + line-height: 18px; + color: #555; + background-color: #f9f9f9; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + cursor: pointer; +} +.download .checkbox:hover { + color: #333; + background-color: #f5f5f5; +} +.download .checkbox small { + font-size: 12px; + color: #777; +} + +/* Variables section */ +#variables label { + margin-bottom: 0; +} + +/* Giant download button */ +.download-btn { + margin: 36px 0 108px; +} +#download p, +#download h4 { + max-width: 50%; + margin: 0 auto; + color: #999; + text-align: center; +} +#download h4 { + margin-bottom: 0; +} +#download p { + margin-bottom: 18px; +} +.download-btn .btn { + display: block; + width: auto; + padding: 19px 24px; + margin-bottom: 27px; + font-size: 30px; + line-height: 1; + text-align: center; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + + + +/* Misc +-------------------------------------------------- */ + +/* Make tables spaced out a bit more */ +h2 + table, +h3 + table, +h4 + table, +h2 + .row { + margin-top: 5px; +} + +/* Example sites showcase */ +.example-sites { + xmargin-left: 20px; +} +.example-sites img { + max-width: 100%; + margin: 0 auto; +} + +.scrollspy-example { + height: 200px; + overflow: auto; + position: relative; +} + + +/* Fake the :focus state to demo it */ +.focused { + border-color: rgba(82,168,236,.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); + -moz-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); + box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6); + outline: 0; +} + +/* For input sizes, make them display block */ +.docs-input-sizes select, +.docs-input-sizes input[type=text] { + display: block; + margin-bottom: 9px; +} + +/* Icons +------------------------- */ +.the-icons { + margin-left: 0; + list-style: none; +} +.the-icons li { + float: left; + width: 25%; + line-height: 25px; +} +.the-icons i:hover { + background-color: rgba(255,0,0,.25); +} + +/* Example page +------------------------- */ +.bootstrap-examples h4 { + margin: 10px 0 5px; +} +.bootstrap-examples p { + font-size: 13px; + line-height: 18px; +} +.bootstrap-examples .thumbnail { + margin-bottom: 9px; + background-color: #fff; +} + + + +/* Bootstrap code examples +-------------------------------------------------- */ + +/* Base class */ +.bs-docs-example { + position: relative; + margin: 15px 0; + padding: 39px 19px 14px; + *padding-top: 19px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +/* Echo out a label for the example */ +.bs-docs-example:after { + content: "Example"; + position: absolute; + top: -1px; + left: -1px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + background-color: #f5f5f5; + border: 1px solid #ddd; + color: #9da0a4; + -webkit-border-radius: 4px 0 4px 0; + -moz-border-radius: 4px 0 4px 0; + border-radius: 4px 0 4px 0; +} + +/* Remove spacing between an example and it's code */ +.bs-docs-example + .prettyprint { + margin-top: -20px; + padding-top: 15px; +} + +/* Tweak examples +------------------------- */ +.bs-docs-example > p:last-child { + margin-bottom: 0; +} +.bs-docs-example .table, +.bs-docs-example .progress, +.bs-docs-example .well, +.bs-docs-example .alert, +.bs-docs-example .hero-unit, +.bs-docs-example .pagination, +.bs-docs-example .navbar, +.bs-docs-example > .nav, +.bs-docs-example blockquote { + margin-bottom: 5px; +} +.bs-docs-example .pagination { + margin-top: 0; +} +.bs-navbar-top-example, +.bs-navbar-bottom-example { + z-index: 1; + padding: 0; + height: 90px; + overflow: hidden; /* cut the drop shadows off */ +} +.bs-navbar-top-example .navbar-fixed-top, +.bs-navbar-bottom-example .navbar-fixed-bottom { + margin-left: 0; + margin-right: 0; +} +.bs-navbar-top-example { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.bs-navbar-top-example:after { + top: auto; + bottom: -1px; + -webkit-border-radius: 0 4px 0 4px; + -moz-border-radius: 0 4px 0 4px; + border-radius: 0 4px 0 4px; +} +.bs-navbar-bottom-example { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.bs-navbar-bottom-example .navbar { + margin-bottom: 0; +} +form.bs-docs-example { + padding-bottom: 19px; +} + +/* Images */ +.bs-docs-example-images img { + margin: 10px; + display: inline-block; +} + +/* Tooltips */ +.bs-docs-tooltip-examples { + text-align: center; + margin: 0 0 10px; + list-style: none; +} +.bs-docs-tooltip-examples li { + display: inline; + padding: 0 10px; +} + +/* Popovers */ +.bs-docs-example-popover { + padding-bottom: 24px; + background-color: #f9f9f9; +} +.bs-docs-example-popover .popover { + position: relative; + display: block; + float: left; + width: 260px; + margin: 20px; +} + +/* Dropdowns */ +.bs-docs-example-submenus { + min-height: 180px; +} +.bs-docs-example-submenus > .pull-left + .pull-left { + margin-left: 20px; +} +.bs-docs-example-submenus .dropup > .dropdown-menu, +.bs-docs-example-submenus .dropdown > .dropdown-menu { + display: block; + position: static; + margin-bottom: 5px; + *width: 180px; +} + + + +/* Responsive docs +-------------------------------------------------- */ + +/* Utility classes table +------------------------- */ +.responsive-utilities th small { + display: block; + font-weight: normal; + color: #999; +} +.responsive-utilities tbody th { + font-weight: normal; +} +.responsive-utilities td { + text-align: center; +} +.responsive-utilities td.is-visible { + color: #468847; + background-color: #dff0d8 !important; +} +.responsive-utilities td.is-hidden { + color: #ccc; + background-color: #f9f9f9 !important; +} + +/* Responsive tests +------------------------- */ +.responsive-utilities-test { + margin-top: 5px; + margin-left: 0; + list-style: none; + overflow: hidden; /* clear floats */ +} +.responsive-utilities-test li { + position: relative; + float: left; + width: 25%; + height: 43px; + font-size: 14px; + font-weight: bold; + line-height: 43px; + color: #999; + text-align: center; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.responsive-utilities-test li + li { + margin-left: 10px; +} +.responsive-utilities-test span { + position: absolute; + top: -1px; + left: -1px; + right: -1px; + bottom: -1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.responsive-utilities-test span { + color: #468847; + background-color: #dff0d8; + border: 1px solid #d6e9c6; +} + + + +/* Sidenav for Docs +-------------------------------------------------- */ + +.bs-docs-sidenav { + width: 228px; + margin: 30px 0 0; + padding: 0; + background-color: #fff; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 4px rgba(0,0,0,.065); + -moz-box-shadow: 0 1px 4px rgba(0,0,0,.065); + box-shadow: 0 1px 4px rgba(0,0,0,.065); +} +.bs-docs-sidenav > li > a { + display: block; + width: 190px \9; + margin: 0 0 -1px; + padding: 8px 14px; + border: 1px solid #e5e5e5; +} +.bs-docs-sidenav > li:first-child > a { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} +.bs-docs-sidenav > li:last-child > a { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} +.bs-docs-sidenav > .active > a { + position: relative; + z-index: 2; + padding: 9px 15px; + border: 0; + text-shadow: 0 1px 0 rgba(0,0,0,.15); + -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.1), inset -1px 0 0 rgba(0,0,0,.1); + -moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.1), inset -1px 0 0 rgba(0,0,0,.1); + box-shadow: inset 1px 0 0 rgba(0,0,0,.1), inset -1px 0 0 rgba(0,0,0,.1); +} +/* Chevrons */ +.bs-docs-sidenav .icon-chevron-right { + float: right; + margin-top: 2px; + margin-right: -6px; + opacity: .25; +} +.bs-docs-sidenav > li > a:hover { + background-color: #f5f5f5; +} +.bs-docs-sidenav a:hover .icon-chevron-right { + opacity: .5; +} +.bs-docs-sidenav .active .icon-chevron-right, +.bs-docs-sidenav .active a:hover .icon-chevron-right { + background-image: url(../img/glyphicons-halflings-white.png); + opacity: 1; +} +.bs-docs-sidenav.affix { + top: 40px; +} +.bs-docs-sidenav.affix-bottom { + position: absolute; + top: auto; + bottom: 270px; +} + + + + +/* Responsive +-------------------------------------------------- */ + +/* Desktop large +------------------------- */ +@media (min-width: 1200px) { + .bs-docs-container { + max-width: 970px; + } + .bs-docs-sidenav { + width: 258px; + } + .bs-docs-sidenav > li > a { + width: 230px \9; /* Override the previous IE8-9 hack */ + } +} + +/* Desktop +------------------------- */ +@media (max-width: 980px) { + /* Unfloat brand */ + body > .navbar-fixed-top .brand { + float: left; + margin-left: 0; + padding-left: 10px; + padding-right: 10px; + } + + /* Inline-block quick links for more spacing */ + .quick-links li { + display: inline-block; + margin: 5px; + } + + /* When affixed, space properly */ + .bs-docs-sidenav { + top: 0; + width: 218px; + margin-top: 30px; + margin-right: 0; + } +} + +/* Tablet to desktop +------------------------- */ +@media (min-width: 768px) and (max-width: 979px) { + /* Remove any padding from the body */ + body { + padding-top: 0; + } + /* Widen masthead and social buttons to fill body padding */ + .jumbotron { + margin-top: -20px; /* Offset bottom margin on .navbar */ + } + /* Adjust sidenav width */ + .bs-docs-sidenav { + width: 166px; + margin-top: 20px; + } + .bs-docs-sidenav.affix { + top: 0; + } +} + +/* Tablet +------------------------- */ +@media (max-width: 767px) { + /* Remove any padding from the body */ + body { + padding-top: 0; + } + + /* Widen masthead and social buttons to fill body padding */ + .jumbotron { + padding: 40px 20px; + margin-top: -20px; /* Offset bottom margin on .navbar */ + margin-right: -20px; + margin-left: -20px; + } + .masthead h1 { + font-size: 90px; + } + .masthead p, + .masthead .btn { + font-size: 24px; + } + .marketing .span4 { + margin-bottom: 40px; + } + .bs-docs-social { + margin: 0 -20px; + } + + /* Space out the show-grid examples */ + .show-grid [class*="span"] { + margin-bottom: 5px; + } + + /* Sidenav */ + .bs-docs-sidenav { + width: auto; + margin-bottom: 20px; + } + .bs-docs-sidenav.affix { + position: static; + width: auto; + top: 0; + } + + /* Unfloat the back to top link in footer */ + .footer { + margin-left: -20px; + margin-right: -20px; + padding-left: 20px; + padding-right: 20px; + } + .footer p { + margin-bottom: 9px; + } +} + +/* Landscape phones +------------------------- */ +@media (max-width: 480px) { + /* Remove padding above jumbotron */ + body { + padding-top: 0; + } + + /* Change up some type stuff */ + h2 small { + display: block; + } + + /* Downsize the jumbotrons */ + .jumbotron h1 { + font-size: 45px; + } + .jumbotron p, + .jumbotron .btn { + font-size: 18px; + } + .jumbotron .btn { + display: block; + margin: 0 auto; + } + + /* center align subhead text like the masthead */ + .subhead h1, + .subhead p { + text-align: center; + } + + /* Marketing on home */ + .marketing h1 { + font-size: 30px; + } + .marketing-byline { + font-size: 18px; + } + + /* center example sites */ + .example-sites { + margin-left: 0; + } + .example-sites > li { + float: none; + display: block; + max-width: 280px; + margin: 0 auto 18px; + text-align: center; + } + .example-sites .thumbnail > img { + max-width: 270px; + } + + /* Do our best to make tables work in narrow viewports */ + table code { + white-space: normal; + word-wrap: break-word; + word-break: break-all; + } + + /* Examples: dropdowns */ + .bs-docs-example-submenus > .pull-left { + float: none; + clear: both; + } + .bs-docs-example-submenus > .pull-left, + .bs-docs-example-submenus > .pull-left + .pull-left { + margin-left: 0; + } + .bs-docs-example-submenus p { + margin-bottom: 0; + } + .bs-docs-example-submenus .dropup > .dropdown-menu, + .bs-docs-example-submenus .dropdown > .dropdown-menu { + margin-bottom: 10px; + float: none; + max-width: 180px; + } + + /* Examples: modal */ + .modal-example .modal { + position: relative; + top: auto; + right: auto; + bottom: auto; + left: auto; + } + + /* Tighten up footer */ + .footer { + padding-top: 20px; + padding-bottom: 20px; + } +} diff --git a/asset/bootstrap/img/glyphicons-halflings-white.png b/asset/bootstrap/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae GIT binary patch literal 8777 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 B7G?kd literal 0 HcmV?d00001 diff --git a/asset/bootstrap/img/glyphicons-halflings.png b/asset/bootstrap/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/asset/bootstrap/js/README.md b/asset/bootstrap/js/README.md new file mode 100644 index 0000000..66903c7 --- /dev/null +++ b/asset/bootstrap/js/README.md @@ -0,0 +1,106 @@ +## 2.0 BOOTSTRAP JS PHILOSOPHY +These are the high-level design rules which guide the development of Bootstrap's plugin apis. + +--- + +### DATA-ATTRIBUTE API + +We believe you should be able to use all plugins provided by Bootstrap purely through the markup API without writing a single line of javascript. + +We acknowledge that this isn't always the most performant and sometimes it may be desirable to turn this functionality off altogether. Therefore, as of 2.0 we provide the ability to disable the data attribute API by unbinding all events on the body namespaced with `'data-api'`. This looks like this: + + $('body').off('.data-api') + +To target a specific plugin, just include the plugins name as a namespace along with the data-api namespace like this: + + $('body').off('.alert.data-api') + +--- + +### PROGRAMMATIC API + +We also believe you should be able to use all plugins provided by Bootstrap purely through the JS API. + +All public APIs should be single, chainable methods, and return the collection acted upon. + + $(".btn.danger").button("toggle").addClass("fat") + +All methods should accept an optional options object, a string which targets a particular method, or null which initiates the default behavior: + + $("#myModal").modal() // initialized with defaults + $("#myModal").modal({ keyboard: false }) // initialized with now keyboard + $("#myModal").modal('show') // initializes and invokes show immediately afterqwe2 + +--- + +### OPTIONS + +Options should be sparse and add universal value. We should pick the right defaults. + +All plugins should have a default object which can be modified to effect all instance's default options. The defaults object should be available via `$.fn.plugin.defaults`. + + $.fn.modal.defaults = { … } + +An options definition should take the following form: + + *noun*: *adjective* - describes or modifies a quality of an instance + +examples: + + backdrop: true + keyboard: false + placement: 'top' + +--- + +### EVENTS + +All events should have an infinitive and past participle form. The infinitive is fired just before an action takes place, the past participle on completion of the action. + + show | shown + hide | hidden + +--- + +### CONSTRUCTORS + +Each plugin should expose it's raw constructor on a `Constructor` property -- accessed in the following way: + + + $.fn.popover.Constructor + +--- + +### DATA ACCESSOR + +Each plugin stores a copy of the invoked class on an object. This class instance can be accessed directly through jQuery's data API like this: + + $('[rel=popover]').data('popover') instanceof $.fn.popover.Constructor + +--- + +### DATA ATTRIBUTES + +Data attributes should take the following form: + +- data-{{verb}}={{plugin}} - defines main interaction +- data-target || href^=# - defined on "control" element (if element controls an element other than self) +- data-{{noun}} - defines class instance options + +examples: + + // control other targets + data-toggle="modal" data-target="#foo" + data-toggle="collapse" data-target="#foo" data-parent="#bar" + + // defined on element they control + data-spy="scroll" + + data-dismiss="modal" + data-dismiss="alert" + + data-toggle="dropdown" + + data-toggle="button" + data-toggle="buttons-checkbox" + data-toggle="buttons-radio" \ No newline at end of file diff --git a/asset/bootstrap/js/application.js b/asset/bootstrap/js/application.js new file mode 100644 index 0000000..f880bc0 --- /dev/null +++ b/asset/bootstrap/js/application.js @@ -0,0 +1,156 @@ +// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT +// IT'S ALL JUST JUNK FOR OUR DOCS! +// ++++++++++++++++++++++++++++++++++++++++++ + +!function ($) { + + $(function(){ + + var $window = $(window) + + // Disable certain links in docs + $('section [href^=#]').click(function (e) { + e.preventDefault() + }) + + // side bar + setTimeout(function () { + $('.bs-docs-sidenav').affix({ + offset: { + top: function () { return $window.width() <= 980 ? 290 : 210 } + , bottom: 270 + } + }) + }, 100) + + // make code pretty + window.prettyPrint && prettyPrint() + + // add-ons + $('.add-on :checkbox').on('click', function () { + var $this = $(this) + , method = $this.attr('checked') ? 'addClass' : 'removeClass' + $(this).parents('.add-on')[method]('active') + }) + + // add tipsies to grid for scaffolding + if ($('#gridSystem').length) { + $('#gridSystem').tooltip({ + selector: '.show-grid > [class*="span"]' + , title: function () { return $(this).width() + 'px' } + }) + } + + // tooltip demo + $('.tooltip-demo').tooltip({ + selector: "a[data-toggle=tooltip]" + }) + + $('.tooltip-test').tooltip() + $('.popover-test').popover() + + // popover demo + $("a[data-toggle=popover]") + .popover() + .click(function(e) { + e.preventDefault() + }) + + // button state demo + $('#fat-btn') + .click(function () { + var btn = $(this) + btn.button('loading') + setTimeout(function () { + btn.button('reset') + }, 3000) + }) + + // carousel demo + $('#myCarousel').carousel() + + // javascript build logic + var inputsComponent = $("#components.download input") + , inputsPlugin = $("#plugins.download input") + , inputsVariables = $("#variables.download input") + + // toggle all plugin checkboxes + $('#components.download .toggle-all').on('click', function (e) { + e.preventDefault() + inputsComponent.attr('checked', !inputsComponent.is(':checked')) + }) + + $('#plugins.download .toggle-all').on('click', function (e) { + e.preventDefault() + inputsPlugin.attr('checked', !inputsPlugin.is(':checked')) + }) + + $('#variables.download .toggle-all').on('click', function (e) { + e.preventDefault() + inputsVariables.val('') + }) + + // request built javascript + $('.download-btn .btn').on('click', function () { + + var css = $("#components.download input:checked") + .map(function () { return this.value }) + .toArray() + , js = $("#plugins.download input:checked") + .map(function () { return this.value }) + .toArray() + , vars = {} + , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png'] + + $("#variables.download input") + .each(function () { + $(this).val() && (vars[ $(this).prev().text() ] = $(this).val()) + }) + + $.ajax({ + type: 'POST' + , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com' + , dataType: 'jsonpi' + , params: { + js: js + , css: css + , vars: vars + , img: img + } + }) + }) + }) + +// Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi +$.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) { + var url = opts.url; + + return { + send: function(_, completeCallback) { + var name = 'jQuery_iframe_' + jQuery.now() + , iframe, form + + iframe = $('' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
'; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ''; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if ( !inst.yearshtml ) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function(value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += ''; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '
'; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate: function(inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ +function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.bind('mouseout', function(event) { + var elem = $( event.target ).closest( selector ); + if ( !elem.length ) { + return; + } + elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); + }) + .bind('mouseover', function(event) { + var elem = $( event.target ).closest( selector ); + if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || + !elem.length ) { + return; + } + elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + elem.addClass('ui-state-hover'); + if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); + if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); + }); +} + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Determine whether an object is an array. */ +function isArray(a) { + return (a && (($.browser.safari && typeof a == 'object' && a.length) || + (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if ( !this.length ) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find('body').append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.8.23"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window['DP_jQuery_' + dpuuid] = $; + +})(jQuery); + +(function( $, undefined ) { + +var uiDialogClasses = + 'ui-dialog ' + + 'ui-widget ' + + 'ui-widget-content ' + + 'ui-corner-all ', + sizeRelatedOptions = { + buttons: true, + height: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + width: true + }, + resizableRelatedOptions = { + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true + }; + +$.widget("ui.dialog", { + options: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: 'close', + dialogClass: '', + draggable: true, + hide: null, + height: 'auto', + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: 'center', + at: 'center', + collision: 'fit', + // ensure that the titlebar is never outside the document + using: function(pos) { + var topOffset = $(this).css(pos).offset().top; + if (topOffset < 0) { + $(this).css('top', pos.top - topOffset); + } + } + }, + resizable: true, + show: null, + stack: true, + title: '', + width: 300, + zIndex: 1000 + }, + + _create: function() { + this.originalTitle = this.element.attr('title'); + // #5742 - .attr() might return a DOMElement + if ( typeof this.originalTitle !== "string" ) { + this.originalTitle = ""; + } + + this.options.title = this.options.title || this.originalTitle; + var self = this, + options = self.options, + + title = options.title || ' ', + titleId = $.ui.dialog.getTitleId(self.element), + + uiDialog = (self.uiDialog = $('
')) + .appendTo(document.body) + .hide() + .addClass(uiDialogClasses + options.dialogClass) + .css({ + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + // setting outline to 0 prevents a border on focus in Mozilla + .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { + if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE) { + + self.close(event); + event.preventDefault(); + } + }) + .attr({ + role: 'dialog', + 'aria-labelledby': titleId + }) + .mousedown(function(event) { + self.moveToTop(false, event); + }), + + uiDialogContent = self.element + .show() + .removeAttr('title') + .addClass( + 'ui-dialog-content ' + + 'ui-widget-content') + .appendTo(uiDialog), + + uiDialogTitlebar = (self.uiDialogTitlebar = $('
')) + .addClass( + 'ui-dialog-titlebar ' + + 'ui-widget-header ' + + 'ui-corner-all ' + + 'ui-helper-clearfix' + ) + .prependTo(uiDialog), + + uiDialogTitlebarClose = $('') + .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'); + }) + .click(function(event) { + self.close(event); + return false; + }) + .appendTo(uiDialogTitlebar), + + uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('')) + .addClass( + 'ui-icon ' + + 'ui-icon-closethick' + ) + .text(options.closeText) + .appendTo(uiDialogTitlebarClose), + + uiDialogTitle = $('') + .addClass('ui-dialog-title') + .attr('id', titleId) + .html(title) + .prependTo(uiDialogTitlebar); + + //handling of deprecated beforeclose (vs beforeClose) option + //Ticket #4669 http://dev.jqueryui.com/ticket/4669 + //TODO: remove in 1.9pre + if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { + options.beforeClose = options.beforeclose; + } + + uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); + + if (options.draggable && $.fn.draggable) { + self._makeDraggable(); + } + if (options.resizable && $.fn.resizable) { + self._makeResizable(); + } + + self._createButtons(options.buttons); + self._isOpen = false; + + if ($.fn.bgiframe) { + uiDialog.bgiframe(); + } + }, + + _init: function() { + if ( this.options.autoOpen ) { + this.open(); + } + }, + + destroy: function() { + var self = this; + + if (self.overlay) { + self.overlay.destroy(); + } + self.uiDialog.hide(); + self.element + .unbind('.dialog') + .removeData('dialog') + .removeClass('ui-dialog-content ui-widget-content') + .hide().appendTo('body'); + self.uiDialog.remove(); + + if (self.originalTitle) { + self.element.attr('title', self.originalTitle); + } + + return self; + }, + + widget: function() { + return this.uiDialog; + }, + + close: function(event) { + var self = this, + maxZ, thisZ; + + if (false === self._trigger('beforeClose', event)) { + return; + } + + if (self.overlay) { + self.overlay.destroy(); + } + self.uiDialog.unbind('keypress.ui-dialog'); + + self._isOpen = false; + + if (self.options.hide) { + self.uiDialog.hide(self.options.hide, function() { + self._trigger('close', event); + }); + } else { + self.uiDialog.hide(); + self._trigger('close', event); + } + + $.ui.dialog.overlay.resize(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if (self.options.modal) { + maxZ = 0; + $('.ui-dialog').each(function() { + if (this !== self.uiDialog[0]) { + thisZ = $(this).css('z-index'); + if(!isNaN(thisZ)) { + maxZ = Math.max(maxZ, thisZ); + } + } + }); + $.ui.dialog.maxZ = maxZ; + } + + return self; + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function(force, event) { + var self = this, + options = self.options, + saveScroll; + + if ((options.modal && !force) || + (!options.stack && !options.modal)) { + return self._trigger('focus', event); + } + + if (options.zIndex > $.ui.dialog.maxZ) { + $.ui.dialog.maxZ = options.zIndex; + } + if (self.overlay) { + $.ui.dialog.maxZ += 1; + self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); + } + + //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. + // http://ui.jquery.com/bugs/ticket/3193 + saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; + $.ui.dialog.maxZ += 1; + self.uiDialog.css('z-index', $.ui.dialog.maxZ); + self.element.attr(saveScroll); + self._trigger('focus', event); + + return self; + }, + + open: function() { + if (this._isOpen) { return; } + + var self = this, + options = self.options, + uiDialog = self.uiDialog; + + self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; + self._size(); + self._position(options.position); + uiDialog.show(options.show); + self.moveToTop(true); + + // prevent tabbing out of modal dialogs + if ( options.modal ) { + uiDialog.bind( "keydown.ui-dialog", function( event ) { + if ( event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + + var tabbables = $(':tabbable', this), + first = tabbables.filter(':first'), + last = tabbables.filter(':last'); + + if (event.target === last[0] && !event.shiftKey) { + first.focus(1); + return false; + } else if (event.target === first[0] && event.shiftKey) { + last.focus(1); + return false; + } + }); + } + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + $(self.element.find(':tabbable').get().concat( + uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( + uiDialog.get()))).eq(0).focus(); + + self._isOpen = true; + self._trigger('open'); + + return self; + }, + + _createButtons: function(buttons) { + var self = this, + hasButtons = false, + uiDialogButtonPane = $('
') + .addClass( + 'ui-dialog-buttonpane ' + + 'ui-widget-content ' + + 'ui-helper-clearfix' + ), + uiButtonSet = $( "
" ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + // if we already have a button pane, remove it + self.uiDialog.find('.ui-dialog-buttonpane').remove(); + + if (typeof buttons === 'object' && buttons !== null) { + $.each(buttons, function() { + return !(hasButtons = true); + }); + } + if (hasButtons) { + $.each(buttons, function(name, props) { + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + var button = $('') + .click(function() { + props.click.apply(self.element[0], arguments); + }) + .appendTo(uiButtonSet); + // can't use .attr( props, true ) with jQuery 1.3.2. + $.each( props, function( key, value ) { + if ( key === "click" ) { + return; + } + if ( key in button ) { + button[ key ]( value ); + } else { + button.attr( key, value ); + } + }); + if ($.fn.button) { + button.button(); + } + }); + uiDialogButtonPane.appendTo(self.uiDialog); + } + }, + + _makeDraggable: function() { + var self = this, + options = self.options, + doc = $(document), + heightBeforeDrag; + + function filteredUi(ui) { + return { + position: ui.position, + offset: ui.offset + }; + } + + self.uiDialog.draggable({ + cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', + handle: '.ui-dialog-titlebar', + containment: 'document', + start: function(event, ui) { + heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); + $(this).height($(this).height()).addClass("ui-dialog-dragging"); + self._trigger('dragStart', event, filteredUi(ui)); + }, + drag: function(event, ui) { + self._trigger('drag', event, filteredUi(ui)); + }, + stop: function(event, ui) { + options.position = [ui.position.left - doc.scrollLeft(), + ui.position.top - doc.scrollTop()]; + $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); + self._trigger('dragStop', event, filteredUi(ui)); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function(handles) { + handles = (handles === undefined ? this.options.resizable : handles); + var self = this, + options = self.options, + // .ui-resizable has position: relative defined in the stylesheet + // but dialogs have to use absolute or fixed positioning + position = self.uiDialog.css('position'), + resizeHandles = (typeof handles === 'string' ? + handles : + 'n,e,s,w,se,sw,ne,nw' + ); + + function filteredUi(ui) { + return { + originalPosition: ui.originalPosition, + originalSize: ui.originalSize, + position: ui.position, + size: ui.size + }; + } + + self.uiDialog.resizable({ + cancel: '.ui-dialog-content', + containment: 'document', + alsoResize: self.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: self._minHeight(), + handles: resizeHandles, + start: function(event, ui) { + $(this).addClass("ui-dialog-resizing"); + self._trigger('resizeStart', event, filteredUi(ui)); + }, + resize: function(event, ui) { + self._trigger('resize', event, filteredUi(ui)); + }, + stop: function(event, ui) { + $(this).removeClass("ui-dialog-resizing"); + options.height = $(this).height(); + options.width = $(this).width(); + self._trigger('resizeStop', event, filteredUi(ui)); + $.ui.dialog.overlay.resize(); + } + }) + .css('position', position) + .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); + }, + + _minHeight: function() { + var options = this.options; + + if (options.height === 'auto') { + return options.minHeight; + } else { + return Math.min(options.minHeight, options.height); + } + }, + + _position: function(position) { + var myAt = [], + offset = [0, 0], + isVisible; + + if (position) { + // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( + // if (typeof position == 'string' || $.isArray(position)) { + // myAt = $.isArray(position) ? position : position.split(' '); + + if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { + myAt = position.split ? position.split(' ') : [position[0], position[1]]; + if (myAt.length === 1) { + myAt[1] = myAt[0]; + } + + $.each(['left', 'top'], function(i, offsetPosition) { + if (+myAt[i] === myAt[i]) { + offset[i] = myAt[i]; + myAt[i] = offsetPosition; + } + }); + + position = { + my: myAt.join(" "), + at: myAt.join(" "), + offset: offset.join(" ") + }; + } + + position = $.extend({}, $.ui.dialog.prototype.options.position, position); + } else { + position = $.ui.dialog.prototype.options.position; + } + + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is(':visible'); + if (!isVisible) { + this.uiDialog.show(); + } + this.uiDialog + // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 + .css({ top: 0, left: 0 }) + .position($.extend({ of: window }, position)); + if (!isVisible) { + this.uiDialog.hide(); + } + }, + + _setOptions: function( options ) { + var self = this, + resizableOptions = {}, + resize = false; + + $.each( options, function( key, value ) { + self._setOption( key, value ); + + if ( key in sizeRelatedOptions ) { + resize = true; + } + if ( key in resizableRelatedOptions ) { + resizableOptions[ key ] = value; + } + }); + + if ( resize ) { + this._size(); + } + if ( this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", resizableOptions ); + } + }, + + _setOption: function(key, value){ + var self = this, + uiDialog = self.uiDialog; + + switch (key) { + //handling of deprecated beforeclose (vs beforeClose) option + //Ticket #4669 http://dev.jqueryui.com/ticket/4669 + //TODO: remove in 1.9pre + case "beforeclose": + key = "beforeClose"; + break; + case "buttons": + self._createButtons(value); + break; + case "closeText": + // ensure that we always pass a string + self.uiDialogTitlebarCloseText.text("" + value); + break; + case "dialogClass": + uiDialog + .removeClass(self.options.dialogClass) + .addClass(uiDialogClasses + value); + break; + case "disabled": + if (value) { + uiDialog.addClass('ui-dialog-disabled'); + } else { + uiDialog.removeClass('ui-dialog-disabled'); + } + break; + case "draggable": + var isDraggable = uiDialog.is( ":data(draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } + + if ( !isDraggable && value ) { + self._makeDraggable(); + } + break; + case "position": + self._position(value); + break; + case "resizable": + // currently resizable, becoming non-resizable + var isResizable = uiDialog.is( ":data(resizable)" ); + if (isResizable && !value) { + uiDialog.resizable('destroy'); + } + + // currently resizable, changing handles + if (isResizable && typeof value === 'string') { + uiDialog.resizable('option', 'handles', value); + } + + // currently non-resizable, becoming resizable + if (!isResizable && value !== false) { + self._makeResizable(value); + } + break; + case "title": + // convert whatever was passed in o a string, for html() to not throw up + $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); + break; + } + + $.Widget.prototype._setOption.apply(self, arguments); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var options = this.options, + nonContentHeight, + minContentHeight, + isVisible = this.uiDialog.is( ":visible" ); + + // reset content sizing + this.element.show().css({ + width: 'auto', + minHeight: 0, + height: 0 + }); + + if (options.minWidth > options.width) { + options.width = options.minWidth; + } + + // reset wrapper sizing + // determine the height of all the non-content elements + nonContentHeight = this.uiDialog.css({ + height: 'auto', + width: options.width + }) + .height(); + minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); + + if ( options.height === "auto" ) { + // only needed for IE6 support + if ( $.support.minHeight ) { + this.element.css({ + minHeight: minContentHeight, + height: "auto" + }); + } else { + this.uiDialog.show(); + var autoHeight = this.element.css( "height", "auto" ).height(); + if ( !isVisible ) { + this.uiDialog.hide(); + } + this.element.height( Math.max( autoHeight, minContentHeight ) ); + } + } else { + this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + } + + if (this.uiDialog.is(':data(resizable)')) { + this.uiDialog.resizable('option', 'minHeight', this._minHeight()); + } + } +}); + +$.extend($.ui.dialog, { + version: "1.8.23", + + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + var id = $el.attr('id'); + if (!id) { + this.uuid += 1; + id = this.uuid; + } + return 'ui-dialog-title-' + id; + }, + + overlay: function(dialog) { + this.$el = $.ui.dialog.overlay.create(dialog); + } +}); + +$.extend($.ui.dialog.overlay, { + instances: [], + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + oldInstances: [], + 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) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ($.ui.dialog.overlay.instances.length) { + $(document).bind($.ui.dialog.overlay.events, function(event) { + // stop events if the z-index of the target is < the z-index of the overlay + // we cannot return true when we don't want to cancel the event (#3523) + if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) { + return false; + } + }); + } + }, 1); + + // allow closing by pressing the escape key + $(document).bind('keydown.dialog-overlay', function(event) { + if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE) { + + dialog.close(event); + event.preventDefault(); + } + }); + + // handle window resize + $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); + } + + var $el = (this.oldInstances.pop() || $('
').addClass('ui-widget-overlay')) + .appendTo(document.body) + .css({ + width: this.width(), + height: this.height() + }); + + if ($.fn.bgiframe) { + $el.bgiframe(); + } + + this.instances.push($el); + return $el; + }, + + destroy: function($el) { + var indexOf = $.inArray($el, this.instances); + if (indexOf != -1){ + this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); + } + + if (this.instances.length === 0) { + $([document, window]).unbind('.dialog-overlay'); + } + + $el.remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + var maxZ = 0; + $.each(this.instances, function() { + maxZ = Math.max(maxZ, this.css('z-index')); + }); + this.maxZ = maxZ; + }, + + height: function() { + var scrollHeight, + offsetHeight; + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if (scrollHeight < offsetHeight) { + return $(window).height() + 'px'; + } else { + return scrollHeight + 'px'; + } + // handle "good" browsers + } else { + return $(document).height() + 'px'; + } + }, + + width: function() { + var scrollWidth, + offsetWidth; + // handle IE + if ( $.browser.msie ) { + scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if (scrollWidth < offsetWidth) { + return $(window).width() + 'px'; + } else { + return scrollWidth + 'px'; + } + // handle "good" browsers + } else { + return $(document).width() + 'px'; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + 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( $, undefined ) { + +$.ui = $.ui || {}; + +var horizontalPositions = /left|center|right/, + verticalPositions = /top|center|bottom/, + center = "center", + support = {}, + _position = $.fn.position, + _offset = $.fn.offset; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var target = $( options.of ), + targetElem = target[0], + collision = ( options.collision || "flip" ).split( " " ), + offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], + targetWidth, + targetHeight, + basePosition; + + if ( targetElem.nodeType === 9 ) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top: 0, left: 0 }; + // TODO: use $.isWindow() in 1.9 + } else if ( targetElem.setTimeout ) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; + } else if ( targetElem.preventDefault ) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + basePosition = { top: options.of.pageY, left: options.of.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + basePosition = target.offset(); + } + + // force my and at to have valid horizontal and veritcal positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[this] || "" ).split( " " ); + if ( pos.length === 1) { + pos = horizontalPositions.test( pos[0] ) ? + pos.concat( [center] ) : + verticalPositions.test( pos[0] ) ? + [ center ].concat( pos ) : + [ center, center ]; + } + pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; + pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; + options[ this ] = pos; + }); + + // normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + // normalize offset option + offset[ 0 ] = parseInt( offset[0], 10 ) || 0; + if ( offset.length === 1 ) { + offset[ 1 ] = offset[ 0 ]; + } + offset[ 1 ] = parseInt( offset[1], 10 ) || 0; + + if ( options.at[0] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[0] === center ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[1] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[1] === center ) { + basePosition.top += targetHeight / 2; + } + + basePosition.left += offset[ 0 ]; + basePosition.top += offset[ 1 ]; + + return this.each(function() { + var elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, + marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, + collisionWidth = elemWidth + marginLeft + + ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), + collisionHeight = elemHeight + marginTop + + ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), + position = $.extend( {}, basePosition ), + collisionPosition; + + if ( options.my[0] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[0] === center ) { + position.left -= elemWidth / 2; + } + + if ( options.my[1] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[1] === center ) { + position.top -= elemHeight / 2; + } + + // prevent fractions if jQuery version doesn't support them (see #5280) + if ( !support.fractions ) { + position.left = Math.round( position.left ); + position.top = Math.round( position.top ); + } + + collisionPosition = { + left: position.left - marginLeft, + top: position.top - marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[i] ] ) { + $.ui.position[ collision[i] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: offset, + my: options.my, + at: options.at + }); + } + }); + + if ( $.fn.bgiframe ) { + elem.bgiframe(); + } + elem.offset( $.extend( position, { using: options.using } ) ); + }); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var win = $( window ), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); + position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); + }, + top: function( position, data ) { + var win = $( window ), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); + position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); + } + }, + + flip: { + left: function( position, data ) { + if ( data.at[0] === center ) { + return; + } + var win = $( window ), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + -data.targetWidth, + offset = -2 * data.offset[ 0 ]; + position.left += data.collisionPosition.left < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + }, + top: function( position, data ) { + if ( data.at[1] === center ) { + return; + } + var win = $( window ), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), + myOffset = data.my[ 1 ] === "top" ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + -data.targetHeight, + offset = -2 * data.offset[ 1 ]; + position.top += data.collisionPosition.top < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + } + } +}; + +// offset setter from jQuery 1.4 +if ( !$.offset.setOffset ) { + $.offset.setOffset = function( elem, options ) { + // set position first, in-case top/left are set even on static elem + if ( /static/.test( $.curCSS( elem, "position" ) ) ) { + elem.style.position = "relative"; + } + var curElem = $( elem ), + curOffset = curElem.offset(), + curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, + curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, + props = { + top: (options.top - curOffset.top) + curTop, + left: (options.left - curOffset.left) + curLeft + }; + + if ( 'using' in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + }; + + $.fn.offset = function( options ) { + var elem = this[ 0 ]; + if ( !elem || !elem.ownerDocument ) { return null; } + if ( options ) { + if ( $.isFunction( options ) ) { + return this.each(function( i ) { + $( this ).offset( options.call( this, i, $( this ).offset() ) ); + }); + } + return this.each(function() { + $.offset.setOffset( this, options ); + }); + } + return _offset.call( this ); + }; +} + +// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css +if ( !$.curCSS ) { + $.curCSS = $.css; +} + +// fraction support test (older versions of jQuery don't support fractions) +(function () { + var body = document.getElementsByTagName( "body" )[ 0 ], + div = document.createElement( "div" ), + testElement, testElementParent, testElementStyle, offset, offsetTotal; + + //Create a "fake body" for testing based on method used in jQuery.support + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + $.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( var i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || document.documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;"; + + offset = $( div ).offset( function( _, offset ) { + return offset; + }).offset(); + + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 ); + support.fractions = offsetTotal > 21 && offsetTotal < 22; +})(); + +}( jQuery )); + +(function( $, undefined ) { + +$.widget( "ui.progressbar", { + options: { + value: 0, + max: 100 + }, + + min: 0, + + _create: function() { + this.element + .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .attr({ + role: "progressbar", + "aria-valuemin": this.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this._value() + }); + + this.valueDiv = $( "
" ) + .appendTo( this.element ); + + this.oldValue = this._value(); + 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(); + + $.Widget.prototype.destroy.apply( this, arguments ); + }, + + value: function( newValue ) { + if ( newValue === undefined ) { + return this._value(); + } + + this._setOption( "value", newValue ); + return this; + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + this.options.value = value; + this._refreshValue(); + if ( this._value() === this.options.max ) { + this._trigger( "complete" ); + } + } + + $.Widget.prototype._setOption.apply( this, arguments ); + }, + + _value: function() { + var val = this.options.value; + // normalize invalid value + if ( typeof val !== "number" ) { + val = 0; + } + return Math.min( this.options.max, Math.max( this.min, val ) ); + }, + + _percentage: function() { + return 100 * this._value() / this.options.max; + }, + + _refreshValue: function() { + var value = this.value(); + var percentage = this._percentage(); + + if ( this.oldValue !== value ) { + this.oldValue = value; + this._trigger( "change" ); + } + + this.valueDiv + .toggle( value > this.min ) + .toggleClass( "ui-corner-right", value === this.options.max ) + .width( percentage.toFixed(0) + "%" ); + this.element.attr( "aria-valuenow", value ); + } +}); + +$.extend( $.ui.progressbar, { + version: "1.8.23" +}); + +})( jQuery ); + +(function( $, undefined ) { + +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) +var numPages = 5; + +$.widget( "ui.slider", $.ui.mouse, { + + widgetEventPrefix: "slide", + + options: { + animate: false, + distance: 0, + max: 100, + min: 0, + orientation: "horizontal", + range: false, + step: 1, + value: 0, + values: null + }, + + _create: function() { + var self = this, + o = this.options, + existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), + handle = "", + handleCount = ( o.values && o.values.length ) || 1, + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass( "ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); + + this.range = $([]); + + if ( o.range ) { + if ( o.range === true ) { + if ( !o.values ) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if ( o.values.length && o.values.length !== 2 ) { + o.values = [ o.values[0], o.values[0] ]; + } + } + + this.range = $( "
" ) + .appendTo( this.element ) + .addClass( "ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); + } + + for ( var i = existingHandles.length; i < handleCount; i += 1 ) { + handles.push( handle ); + } + + this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); + + this.handle = this.handles.eq( 0 ); + + this.handles.add( this.range ).filter( "a" ) + .click(function( event ) { + event.preventDefault(); + }) + .hover(function() { + if ( !o.disabled ) { + $( this ).addClass( "ui-state-hover" ); + } + }, function() { + $( this ).removeClass( "ui-state-hover" ); + }) + .focus(function() { + if ( !o.disabled ) { + $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); + $( this ).addClass( "ui-state-focus" ); + } else { + $( this ).blur(); + } + }) + .blur(function() { + $( this ).removeClass( "ui-state-focus" ); + }); + + this.handles.each(function( i ) { + $( this ).data( "index.ui-slider-handle", i ); + }); + + this.handles + .keydown(function( event ) { + var index = $( this ).data( "index.ui-slider-handle" ), + allowed, + curVal, + newVal, + step; + + if ( self.options.disabled ) { + return; + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + event.preventDefault(); + if ( !self._keySliding ) { + self._keySliding = true; + $( this ).addClass( "ui-state-active" ); + allowed = self._start( event, index ); + if ( allowed === false ) { + return; + } + } + break; + } + + step = self.options.step; + if ( self.options.values && self.options.values.length ) { + curVal = newVal = self.values( index ); + } else { + curVal = newVal = self.value(); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + newVal = self._valueMin(); + break; + case $.ui.keyCode.END: + newVal = self._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if ( curVal === self._valueMax() ) { + return; + } + newVal = self._trimAlignValue( curVal + step ); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if ( curVal === self._valueMin() ) { + return; + } + newVal = self._trimAlignValue( curVal - step ); + break; + } + + self._slide( event, index, newVal ); + }) + .keyup(function( event ) { + var index = $( this ).data( "index.ui-slider-handle" ); + + if ( self._keySliding ) { + self._keySliding = false; + self._stop( event, index ); + self._change( event, index ); + $( this ).removeClass( "ui-state-active" ); + } + + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + destroy: function() { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass( "ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" ) + .removeData( "slider" ) + .unbind( ".slider" ); + + this._mouseDestroy(); + + return this; + }, + + _mouseCapture: function( event ) { + var o = this.options, + position, + normValue, + distance, + closestHandle, + self, + index, + allowed, + offset, + mouseOverHandle; + + if ( o.disabled ) { + return false; + } + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x: event.pageX, y: event.pageY }; + normValue = this._normValueFromMouse( position ); + distance = this._valueMax() - this._valueMin() + 1; + self = this; + this.handles.each(function( i ) { + var thisDistance = Math.abs( normValue - self.values(i) ); + if ( distance > thisDistance ) { + distance = thisDistance; + closestHandle = $( this ); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if( o.range === true && this.values(1) === o.min ) { + index += 1; + closestHandle = $( this.handles[index] ); + } + + allowed = this._start( event, index ); + if ( allowed === false ) { + return false; + } + this._mouseSliding = true; + + self._handleIndex = index; + + closestHandle + .addClass( "ui-state-active" ) + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - ( closestHandle.width() / 2 ), + top: event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - + ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) + }; + + if ( !this.handles.hasClass( "ui-state-hover" ) ) { + this._slide( event, index, normValue ); + } + this._animateOff = true; + return true; + }, + + _mouseStart: function( event ) { + return true; + }, + + _mouseDrag: function( event ) { + var position = { x: event.pageX, y: event.pageY }, + normValue = this._normValueFromMouse( position ); + + this._slide( event, this._handleIndex, normValue ); + + return false; + }, + + _mouseStop: function( event ) { + this.handles.removeClass( "ui-state-active" ); + this._mouseSliding = false; + + this._stop( event, this._handleIndex ); + this._change( event, this._handleIndex ); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation: function() { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse: function( position ) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if ( this.orientation === "horizontal" ) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + } + + percentMouse = ( pixelMouse / pixelTotal ); + if ( percentMouse > 1 ) { + percentMouse = 1; + } + if ( percentMouse < 0 ) { + percentMouse = 0; + } + if ( this.orientation === "vertical" ) { + percentMouse = 1 - percentMouse; + } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue( valueMouse ); + }, + + _start: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + return this._trigger( "start", event, uiHash ); + }, + + _slide: function( event, index, newVal ) { + var otherVal, + newValues, + allowed; + + if ( this.options.values && this.options.values.length ) { + otherVal = this.values( index ? 0 : 1 ); + + if ( ( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if ( newVal !== this.values( index ) ) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal, + values: newValues + } ); + otherVal = this.values( index ? 0 : 1 ); + if ( allowed !== false ) { + this.values( index, newVal, true ); + } + } + } else { + if ( newVal !== this.value() ) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal + } ); + if ( allowed !== false ) { + this.value( newVal ); + } + } + } + }, + + _stop: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "stop", event, uiHash ); + }, + + _change: function( event, index ) { + if ( !this._keySliding && !this._mouseSliding ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "change", event, uiHash ); + } + }, + + value: function( newValue ) { + if ( arguments.length ) { + this.options.value = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, 0 ); + return; + } + + return this._value(); + }, + + values: function( index, newValue ) { + var vals, + newValues, + i; + + if ( arguments.length > 1 ) { + this.options.values[ index ] = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, index ); + return; + } + + if ( arguments.length ) { + if ( $.isArray( arguments[ 0 ] ) ) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for ( i = 0; i < vals.length; i += 1 ) { + vals[ i ] = this._trimAlignValue( newValues[ i ] ); + this._change( null, i ); + } + this._refreshValue(); + } else { + if ( this.options.values && this.options.values.length ) { + return this._values( index ); + } else { + return this.value(); + } + } + } else { + return this._values(); + } + }, + + _setOption: function( key, value ) { + var i, + valsLength = 0; + + if ( $.isArray( this.options.values ) ) { + valsLength = this.options.values.length; + } + + $.Widget.prototype._setOption.apply( this, arguments ); + + switch ( key ) { + case "disabled": + if ( value ) { + this.handles.filter( ".ui-state-focus" ).blur(); + this.handles.removeClass( "ui-state-hover" ); + this.handles.propAttr( "disabled", true ); + this.element.addClass( "ui-disabled" ); + } else { + this.handles.propAttr( "disabled", false ); + this.element.removeClass( "ui-disabled" ); + } + break; + 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 = true; + this._refreshValue(); + this._change( null, 0 ); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for ( i = 0; i < valsLength; i += 1 ) { + this._change( null, i ); + } + this._animateOff = false; + break; + } + }, + + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value: function() { + var val = this.options.value; + val = this._trimAlignValue( val ); + + return val; + }, + + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values: function( index ) { + var val, + vals, + i; + + if ( arguments.length ) { + val = this.options.values[ index ]; + val = this._trimAlignValue( val ); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for ( i = 0; i < vals.length; i+= 1) { + vals[ i ] = this._trimAlignValue( vals[ i ] ); + } + + return vals; + } + }, + + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function( val ) { + if ( val <= this._valueMin() ) { + return this._valueMin(); + } + if ( val >= this._valueMax() ) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat( alignValue.toFixed(5) ); + }, + + _valueMin: function() { + return this.options.min; + }, + + _valueMax: function() { + return this.options.max; + }, + + _refreshValue: function() { + var oRange = this.options.range, + o = this.options, + self = this, + animate = ( !this._animateOff ) ? o.animate : false, + valPercent, + _set = {}, + lastValPercent, + value, + valueMin, + valueMax; + + if ( this.options.values && this.options.values.length ) { + this.handles.each(function( i, j ) { + valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + if ( self.options.range === true ) { + if ( self.orientation === "horizontal" ) { + if ( i === 0 ) { + self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); + } + if ( i === 1 ) { + self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } else { + if ( i === 0 ) { + self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); + } + if ( i === 1 ) { + self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + lastValPercent = valPercent; + }); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + + if ( oRange === "min" && this.orientation === "horizontal" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "horizontal" ) { + this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + if ( oRange === "min" && this.orientation === "vertical" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "vertical" ) { + this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + +}); + +$.extend( $.ui.slider, { + version: "1.8.23" +}); + +}(jQuery)); + +(function( $, undefined ) { + +var tabId = 0, + listId = 0; + +function getNextTabId() { + return ++tabId; +} + +function getNextListId() { + return ++listId; +} + +$.widget( "ui.tabs", { + options: { + add: null, + ajaxOptions: null, + cache: false, + cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + collapsible: false, + disable: null, + disabled: [], + enable: null, + event: "click", + fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } + idPrefix: "ui-tabs-", + load: null, + panelTemplate: "
", + remove: null, + select: null, + show: null, + spinner: "Loading…", + tabTemplate: "
  • #{label}
  • " + }, + + _create: function() { + this._tabify( true ); + }, + + _setOption: function( key, value ) { + if ( key == "selected" ) { + if (this.options.collapsible && value == this.options.selected ) { + return; + } + this.select( value ); + } else { + this.options[ key ] = value; + this._tabify(); + } + }, + + _tabId: function( a ) { + return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || + this.options.idPrefix + getNextTabId(); + }, + + _sanitizeSelector: function( hash ) { + // we need this because an id may contain a ":" + return hash.replace( /:/g, "\\:" ); + }, + + _cookie: function() { + var cookie = this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); + return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); + }, + + _ui: function( tab, panel ) { + return { + tab: tab, + panel: panel, + index: this.anchors.index( tab ) + }; + }, + + _cleanup: function() { + // restore all former loading tabs labels + 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 ) { + var self = this, + o = this.options, + fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash + + this.list = this.element.find( "ol,ul" ).eq( 0 ); + this.lis = $( " > li:has(a[href])", this.list ); + this.anchors = this.lis.map(function() { + return $( "a", this )[ 0 ]; + }); + this.panels = $( [] ); + + this.anchors.each(function( i, a ) { + var href = $( a ).attr( "href" ); + // For dynamically created HTML that contains a hash as href IE < 8 expands + // such href to the full page url with hash and then misinterprets tab as ajax. + // Same consideration applies for an added tab with a fragment identifier + // since a[href=#fragment-identifier] does unexpectedly not match. + // Thus normalize href attribute... + 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; + } + + // inline tab + if ( fragmentId.test( href ) ) { + self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); + // remote tab + // prevent loading the page itself if href is just "#" + } else if ( href && href !== "#" ) { + // required for restore on destroy + $.data( a, "href.tabs", href ); + + // TODO until #3808 is fixed strip fragment identifier from url + // (IE fails to load from such url) + $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); + + var id = self._tabId( a ); + a.href = "#" + id; + var $panel = self.element.find( "#" + 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 ); + // invalid tab href + } else { + o.disabled.push( i ); + } + }); + + // initialization from scratch + if ( init ) { + // attach necessary classes for styling + 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" ); + + // Selected tab + // use "selected" option or try to retrieve: + // 1. from fragment identifier in url + // 2. from cookie + // 3. from selected class attribute on
  • + 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 || ( this.lis.length ? 0 : -1 ); + } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release + o.selected = -1; + } + + // sanity check - default to first tab... + o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) + ? o.selected + : 0; + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + // A selected tab cannot become disabled. + 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 ); + } + + // highlight selected tab + this.panels.addClass( "ui-tabs-hide" ); + this.lis.removeClass( "ui-tabs-selected ui-state-active" ); + // check for length avoids error when initializing empty list + if ( o.selected >= 0 && this.anchors.length ) { + self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); + this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); + + // seems to be expected behavior that the show callback is fired + self.element.queue( "tabs", function() { + self._trigger( "show", null, + self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); + }); + + this.load( o.selected ); + } + + // clean up to avoid memory leaks in certain versions of IE 6 + // TODO: namespace this event + $( window ).bind( "unload", function() { + self.lis.add( self.anchors ).unbind( ".tabs" ); + self.lis = self.anchors = self.panels = null; + }); + // update selected after add/remove + } else { + o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + } + + // update collapsible + // TODO: use .toggleClass() + this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); + + // set or update cookie after init and add/remove respectively + if ( o.cookie ) { + this._cookie( o.selected, o.cookie ); + } + + // disable tabs + for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { + $( li )[ $.inArray( i, o.disabled ) != -1 && + // TODO: use .toggleClass() + !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); + } + + // reset cache if switching from cached to not cached + if ( o.cache === false ) { + this.anchors.removeData( "cache.tabs" ); + } + + // remove all handlers before, tabify may run on existing tabs after add or option change + 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" ) ); + }); + } + + // set up animations + var hideFx, showFx; + if ( o.fx ) { + if ( $.isArray( o.fx ) ) { + hideFx = o.fx[ 0 ]; + showFx = o.fx[ 1 ]; + } else { + hideFx = showFx = o.fx; + } + } + + // Reset certain styles left over from animation + // and prevent IE's ClearType bug... + function resetStyle( $el, fx ) { + $el.css( "display", "" ); + if ( !$.support.opacity && fx.opacity ) { + $el[ 0 ].style.removeAttribute( "filter" ); + } + } + + // Show a tab... + var showTab = showFx + ? function( clicked, $show ) { + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way + .animate( showFx, showFx.duration || "normal", function() { + resetStyle( $show, showFx ); + self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); + }); + } + : function( clicked, $show ) { + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + $show.removeClass( "ui-tabs-hide" ); + self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); + }; + + // Hide a tab, $show is optional... + var hideTab = hideFx + ? function( clicked, $hide ) { + $hide.animate( hideFx, hideFx.duration || "normal", function() { + self.lis.removeClass( "ui-tabs-selected ui-state-active" ); + $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" ); + $hide.addClass( "ui-tabs-hide" ); + self.element.dequeue( "tabs" ); + }; + + // attach tab event handler, unbind to avoid duplicates from former tabifying... + this.anchors.bind( o.event + ".tabs", function() { + var el = this, + $li = $(el).closest( "li" ), + $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), + $show = self.element.find( self._sanitizeSelector( el.hash ) ); + + // If tab is already selected and not collapsible or tab disabled or + // or is already loading or click callback returns false stop here. + // Check if click handler returns false last so that it is not executed + // for a disabled or loading tab! + if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || + $li.hasClass( "ui-state-disabled" ) || + $li.hasClass( "ui-state-processing" ) || + self.panels.filter( ":animated" ).length || + self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { + this.blur(); + return false; + } + + o.selected = self.anchors.index( this ); + + self.abort(); + + // if tab may be closed + 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 ); + }); + + // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 + self.load( self.anchors.index( this ) ); + + this.blur(); + return false; + } + } + + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + // show new tab + 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."; + } + + // Prevent IE from keeping other link focussed when using the back button + // and remove dotted border from clicked link. This is controlled via CSS + // in modern browsers; blur() removes focus from address bar in Firefox + // which can become a usability and annoying problem with tabs('rotate'). + if ( $.browser.msie ) { + this.blur(); + } + }); + + // disable click in any case + this.anchors.bind( "click.tabs", function(){ + return false; + }); + }, + + _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. + // also sanitizes numerical indexes to valid values. + if ( typeof index == "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); + } + + return index; + }, + + 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 ); + } + + return this; + }, + + 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 ); + + // try to find an existing element before creating a new one + var $panel = self.element.find( "#" + 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 ) { + o.selected = 0; + $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 ] ) ); + return this; + }, + + remove: function( index ) { + index = this._getIndex( index ); + var o = this.options, + $li = this.lis.eq( index ).remove(), + $panel = this.panels.eq( index ).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + 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 ] ) ); + return this; + }, + + enable: function( index ) { + index = this._getIndex( 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 ] ) ); + return this; + }, + + disable: function( index ) { + index = this._getIndex( index ); + var self = this, o = this.options; + // cannot disable already selected tab + 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 ] ) ); + } + + return this; + }, + + select: function( index ) { + index = this._getIndex( index ); + if ( index == -1 ) { + if ( this.options.collapsible && this.options.selected != -1 ) { + index = this.options.selected; + } else { + return this; + } + } + this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); + return this; + }, + + load: function( index ) { + index = this._getIndex( index ); + var self = this, + o = this.options, + a = this.anchors.eq( index )[ 0 ], + url = $.data( a, "load.tabs" ); + + this.abort(); + + // not remote or from cache + if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { + this.element.dequeue( "tabs" ); + return; + } + + // load remote from here on + 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.element.find( self._sanitizeSelector( a.hash ) ).html( r ); + + // take care of tab labels + 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 ) {} + }, + error: function( xhr, s, e ) { + // take care of tab labels + self._cleanup(); + + self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + o.ajaxOptions.error( xhr, s, index, a ); + } + catch ( e ) {} + } + } ) ); + + // last, so that load event is fired before show... + self.element.dequeue( "tabs" ); + + return this; + }, + + abort: function() { + // stop possibly running animations + this.element.queue( [] ); + this.panels.stop( false, true ); + + // "tabs" queue must not contain more than two elements, + // which are the callbacks for the latest clicked tab... + this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); + + // terminate pending requests from other tabs + if ( this.xhr ) { + this.xhr.abort(); + delete this.xhr; + } + + // take care of tab labels + this._cleanup(); + return this; + }, + + url: function( index, url ) { + this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); + return this; + }, + + length: function() { + return this.anchors.length; + } +}); + +$.extend( $.ui.tabs, { + version: "1.8.23" +}); + +/* + * Tabs Extensions + */ + +/* + * Rotate + */ +$.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) { // in case of a true click + self.rotate(null); + } + } + : function( e ) { + rotate(); + }); + + // start rotation + if ( ms ) { + this.element.bind( "tabsshow", rotate ); + this.anchors.bind( o.event + ".tabs", stop ); + rotate(); + // stop rotation + } else { + clearTimeout( self.rotation ); + this.element.unbind( "tabsshow", rotate ); + this.anchors.unbind( o.event + ".tabs", stop ); + delete this._rotate; + delete this._unrotate; + } + + return this; + } +}); + +})( jQuery ); \ No newline at end of file diff --git a/asset/slimscroll/jquery.slimscroll.min.js b/asset/slimscroll/jquery.slimscroll.min.js new file mode 100644 index 0000000..4a65411 --- /dev/null +++ b/asset/slimscroll/jquery.slimscroll.min.js @@ -0,0 +1,15 @@ +/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * Version: 1.1.1 + * + */ +(function(f){jQuery.fn.extend({slimScroll:function(l){var a=f.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:0.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200},l);this.each(function(){function r(d){if(n){d=d||window.event;var c=0;d.wheelDelta&&(c=-d.wheelDelta/ +120);d.detail&&(c=d.detail/3);f(d.target||d.srcTarget).closest("."+a.wrapperClass).is(b.parent())&&g(c,!0);d.preventDefault&&!p&&d.preventDefault();p||(d.returnValue=!1)}}function g(d,f,h){var e=d,g=b.outerHeight()-c.outerHeight();f&&(e=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),e=Math.min(Math.max(e,0),g),e=0=b.outerHeight()?p=!0:(c.stop(!0,!0).fadeIn("fast"),a.railVisible&&h.stop(!0,!0).fadeIn("fast"))}function m(){a.alwaysVisible||(w=setTimeout(function(){if((!a.disableFadeOut||!n)&&!u&&!v)c.fadeOut("slow"),h.fadeOut("slow")},1E3))}var n,u,v,w,y,q,j,x,B=30,p=!1,b=f(this);if(b.parent().hasClass(a.wrapperClass)){var k=b.scrollTop(),c=b.parent().find("."+a.barClass),h=b.parent().find("."+a.railClass);t();if(f.isPlainObject(l)){if("scrollTo"in l)k= +parseInt(a.scrollTo);else if("scrollBy"in l)k+=parseInt(a.scrollBy);else if("destroy"in l){c.remove();h.remove();b.unwrap();return}g(k,!1,!0)}}else{a.height="auto"==a.height?b.parent().innerHeight():a.height;k=f("
    ").addClass(a.wrapperClass).css({position:"relative",overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden",width:a.width,height:a.height});var h=f("
    ").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&& +a.railVisible?"block":"none","border-radius":a.size,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=f("
    ").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?"block":"none","border-radius":a.size,BorderRadius:a.size,MozBorderRadius:a.size,WebkitBorderRadius:a.size,zIndex:99}),z="right"==a.position?{right:a.distance}:{left:a.distance};h.css(z);c.css(z);b.wrap(k);b.parent().append(c);b.parent().append(h); +a.railDraggable&&c.draggable({axis:"y",containment:"parent",start:function(){v=!0},stop:function(){v=!1;m()},drag:function(){g(0,f(this).position().top,!1)}});h.hover(function(){s()},function(){m()});c.hover(function(){u=!0},function(){u=!1});b.hover(function(){n=!0;s();m()},function(){n=!1;m()});b.bind("touchstart",function(a){a.originalEvent.touches.length&&(y=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){b.originalEvent.preventDefault();b.originalEvent.touches.length&&g((y- +b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0)});"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),g(0,!0)):"top"!==a.start&&(g(f(a.start).position().top,null,!0),a.alwaysVisible||c.hide());A();t()}});return this}});jQuery.fn.extend({slimscroll:jQuery.fn.slimScroll})})(jQuery); \ No newline at end of file diff --git a/asset/tablesorter/demo_table.css b/asset/tablesorter/demo_table.css new file mode 100644 index 0000000..7839c7e --- /dev/null +++ b/asset/tablesorter/demo_table.css @@ -0,0 +1,577 @@ +/* + * File: demo_table.css + * CVS: $Id$ + * Description: CSS descriptions for DataTables demo pages + * Author: Allan Jardine + * Created: Tue May 12 06:47:22 BST 2009 + * Modified: $Date$ by $Author$ + * Language: CSS + * Project: DataTables + * + * Copyright 2009 Allan Jardine. All Rights Reserved. + * + * *************************************************************************** + * DESCRIPTION + * + * The styles given here are suitable for the demos that are used with the standard DataTables + * distribution (see www.datatables.net). You will most likely wish to modify these styles to + * meet the layout requirements of your site. + * + * Common issues: + * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is + * no conflict between the two pagination types. If you want to use full_numbers pagination + * ensure that you either have "example_alt_pagination" as a body class name, or better yet, + * modify that selector. + * Note that the path used for Images is relative. All images are by default located in + * ../images/ - relative to this CSS file. + */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables features + */ + +.dataTables_wrapper { + position: relative; + clear: both; + zoom: 1; /* Feeling sorry for IE */ +} + +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + +.dataTables_length { + width: 40%; + float: left; +} + +.dataTables_filter { + width: 50%; + float: right; + text-align: right; +} + +.dataTables_info { + width: 60%; + float: left; +} + +.dataTables_paginate { + float: right; + text-align: right; +} + +/* Pagination nested */ +.paginate_disabled_previous, .paginate_enabled_previous, +.paginate_disabled_next, .paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, .paginate_enabled_previous:hover, +.paginate_disabled_next:hover, .paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, .paginate_enabled_previous:active, +.paginate_disabled_next:active, .paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, .paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, .paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_disabled_previous { + background: url('images/back_disabled.png') no-repeat top left; +} + +.paginate_enabled_previous { + background: url('images/back_enabled.png') no-repeat top left; +} +.paginate_enabled_previous:hover { + background: url('images/back_enabled_hover.png') no-repeat top left; +} + +.paginate_disabled_next { + background: url('images/forward_disabled.png') no-repeat top right; +} + +.paginate_enabled_next { + background: url('images/forward_enabled.png') no-repeat top right; +} +.paginate_enabled_next:hover { + background: url('images/forward_enabled_hover.png') no-repeat top right; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables display + */ +table.display { + margin: 0 auto; + clear: both; + width: 100%; + + /* Note Firefox 3.5 and before have a bug with border-collapse + * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 ) + * border-spacing: 0; is one possible option. Conditional-css.com is + * useful for this kind of thing + * + * Further note IE 6/7 has problems when calculating widths with border width. + * It subtracts one px relative to the other browsers from the first column, and + * adds one to the end... + * + * If you want that effect I'd suggest setting a border-top/left on th/td's and + * then filling in the gaps with other borders. + */ +} + +table.display thead th { + padding: 3px 18px 3px 10px; + border-bottom: 1px solid black; + font-weight: bold; + cursor: pointer; + * cursor: hand; +} + +table.display tfoot th { + padding: 3px 18px 3px 10px; + border-top: 1px solid black; + font-weight: bold; +} + +table.display tr.heading2 td { + border-bottom: 1px solid #aaa; +} + +table.display td { + padding: 3px 10px; +} + +table.display td.center { + text-align: center; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables sorting + */ + +.sorting_asc { + background: url('images/sort_asc.png') no-repeat center right; +} + +.sorting_desc { + background: url('images/sort_desc.png') no-repeat center right; +} + +.sorting { + background: url('images/sort_both.png') no-repeat center right; +} + +.sorting_asc_disabled { + background: url('images/sort_asc_disabled.png') no-repeat center right; +} + +.sorting_desc_disabled { + background: url('images/sort_desc_disabled.png') no-repeat center right; +} + +table.display thead th:active, +table.display thead td:active { + outline: none; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables row classes + */ +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + +table.display tr.odd.gradeC { + background-color: #ddddff; +} + +table.display tr.even.gradeC { + background-color: #eeeeff; +} + +table.display tr.odd.gradeX { + background-color: #ffdddd; +} + +table.display tr.even.gradeX { + background-color: #ffeeee; +} + +table.display tr.odd.gradeU { + background-color: #ddd; +} + +table.display tr.even.gradeU { + background-color: #eee; +} + + +tr.odd { + background-color: #E2E4FF; +} + +tr.even { + background-color: white; +} + + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Misc + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + +.top, .bottom { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +.top .dataTables_info { + float: none; +} + +.clear { + clear: both; +} + +.dataTables_empty { + text-align: center; +} + +tfoot input { + margin: 0.5em 0; + width: 100%; + color: #444; +} + +tfoot input.search_init { + color: #999; +} + +td.group { + background-color: #d1cfd0; + border-bottom: 2px solid #A19B9E; + border-top: 2px solid #A19B9E; +} + +td.details { + background-color: #d1cfd0; + border: 2px solid #A19B9E; +} + + +.example_alt_pagination div.dataTables_info { + width: 40%; +} + +.paging_full_numbers { + width: 400px; + height: 22px; + line-height: 22px; +} + +.paging_full_numbers a:active { + outline: none +} + +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, + .paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + +table.display tr.even.row_selected td { + background-color: #B0BED9; +} + +table.display tr.odd.row_selected td { + background-color: #9FAFD1; +} + + +/* + * Sorting classes for columns + */ +/* For the standard odd/even */ +tr.odd td.sorting_1 { + background-color: #D3D6FF; +} + +tr.odd td.sorting_2 { + background-color: #DADCFF; +} + +tr.odd td.sorting_3 { + background-color: #E0E2FF; +} + +tr.even td.sorting_1 { + background-color: #EAEBFF; +} + +tr.even td.sorting_2 { + background-color: #F2F3FF; +} + +tr.even td.sorting_3 { + background-color: #F9F9FF; +} + + +/* For the Conditional-CSS grading rows */ +/* + Colour calculations (based off the main row colours) + Level 1: + dd > c4 + ee > d5 + Level 2: + dd > d1 + ee > e2 + */ +tr.odd.gradeA td.sorting_1 { + background-color: #c4ffc4; +} + +tr.odd.gradeA td.sorting_2 { + background-color: #d1ffd1; +} + +tr.odd.gradeA td.sorting_3 { + background-color: #d1ffd1; +} + +tr.even.gradeA td.sorting_1 { + background-color: #d5ffd5; +} + +tr.even.gradeA td.sorting_2 { + background-color: #e2ffe2; +} + +tr.even.gradeA td.sorting_3 { + background-color: #e2ffe2; +} + +tr.odd.gradeC td.sorting_1 { + background-color: #c4c4ff; +} + +tr.odd.gradeC td.sorting_2 { + background-color: #d1d1ff; +} + +tr.odd.gradeC td.sorting_3 { + background-color: #d1d1ff; +} + +tr.even.gradeC td.sorting_1 { + background-color: #d5d5ff; +} + +tr.even.gradeC td.sorting_2 { + background-color: #e2e2ff; +} + +tr.even.gradeC td.sorting_3 { + background-color: #e2e2ff; +} + +tr.odd.gradeX td.sorting_1 { + background-color: #ffc4c4; +} + +tr.odd.gradeX td.sorting_2 { + background-color: #ffd1d1; +} + +tr.odd.gradeX td.sorting_3 { + background-color: #ffd1d1; +} + +tr.even.gradeX td.sorting_1 { + background-color: #ffd5d5; +} + +tr.even.gradeX td.sorting_2 { + background-color: #ffe2e2; +} + +tr.even.gradeX td.sorting_3 { + background-color: #ffe2e2; +} + +tr.odd.gradeU td.sorting_1 { + background-color: #c4c4c4; +} + +tr.odd.gradeU td.sorting_2 { + background-color: #d1d1d1; +} + +tr.odd.gradeU td.sorting_3 { + background-color: #d1d1d1; +} + +tr.even.gradeU td.sorting_1 { + background-color: #d5d5d5; +} + +tr.even.gradeU td.sorting_2 { + background-color: #e2e2e2; +} + +tr.even.gradeU td.sorting_3 { + background-color: #e2e2e2; +} + + +/* + * Row highlighting example + */ +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted { + background-color: #ECFFB3; +} + +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted { + background-color: #E6FF99; +} + +.ex_highlight_row #example tr.even:hover { + background-color: #ECFFB3; +} + +.ex_highlight_row #example tr.even:hover td.sorting_1 { + background-color: #DDFF75; +} + +.ex_highlight_row #example tr.even:hover td.sorting_2 { + background-color: #E7FF9E; +} + +.ex_highlight_row #example tr.even:hover td.sorting_3 { + background-color: #E2FF89; +} + +.ex_highlight_row #example tr.odd:hover { + background-color: #E6FF99; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_1 { + background-color: #D6FF5C; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_2 { + background-color: #E0FF84; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_3 { + background-color: #DBFF70; +} + + +/* + * KeyTable + */ +table.KeyTable td { + border: 3px solid transparent; +} + +table.KeyTable td.focus { + border: 3px solid #3366FF; +} + +table.display tr.gradeA { + background-color: #eeffee; +} + +table.display tr.gradeC { + background-color: #ddddff; +} + +table.display tr.gradeX { + background-color: #ffdddd; +} + +table.display tr.gradeU { + background-color: #ddd; +} + +div.box { + height: 100px; + padding: 10px; + overflow: auto; + border: 1px solid #8080FF; + background-color: #E5E5FF; +} diff --git a/asset/tablesorter/images/Sorting icons.psd b/asset/tablesorter/images/Sorting icons.psd new file mode 100644 index 0000000000000000000000000000000000000000..53b2e06850767cb57c52b316f0b845b1a8e0ca0e GIT binary patch literal 27490 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 Y16@Zf7?Q8!JB-NJ(KYBs*Ff|C0Zg4MIsgCw literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/back_disabled.png b/asset/tablesorter/images/back_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..881de7976ff98955e2a5487dca66e618a0655f3d GIT binary patch literal 1361 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsVin+1c5}%-r12$=KP@(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1OVZUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZnv1?G!Lpb z1-DzwaO%|uIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@i-f{BMZ3YI$qn<8~Ar-gQ zOt$tu93XPMc=CmoA1oW4o1+WYIB!k3r72K4*@xA>;l+b1ClB@qaOE!8@r8RwiN1wc zl+_Cb3(lEQAv#$bmh>Mfe(I7Woy4{G!}EFf?)^FUc%F02^;EH~5owLt3k}+qS-P)U z616t%^wT0PX2liq$807FHoQ4d$0`5rkQ{U2Kkgclu0)Awnd5T>ob((vrABTq*u(RS z>E?oy`!@uw+@i*D$dKV&#I(EL&;9;u$GTQAMM5faVZejQCzo(NvvlZ75dZt%IYnd( z*RL;GX3W}R-P)5>-Zsu`&nUT&Ho^GzHq{#}Ya$hT91>M0@O`!9^}b&yQ@87fac$Vj zkb72h`!2pMTYunpu!r@;1)uFRXDvHO zu{mw?PmW#JOy1f}J}ILj)G2cQ^TrhhTtyr5@7eCYm=Uoy?6qTPsOnt5?2i>S(pg>~ z>M~M93=YlxcD}*xKl_@hz5j0IZGT@9Yu_^8_RN8=&YkAdFR(fGAAWd4CvkG#0^hlN z8>(g;?I=2=cEEAHaL+WiOvRp~fl`n5dTf5V)bNv|ZcjyzLHRnz@2)SdPWo#3tF@Nf ZfT6u;&2Oo-XD5RSIZszVmvv4FO#nm}^+Nyv literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/back_enabled.png b/asset/tablesorter/images/back_enabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c608682b04a6d9b8002602450c8ef7e80ebba099 GIT binary patch literal 1379 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 bdL|wQU%!)=<|i%z6_yO1u6{1-oD!M<;V$ow literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/forward_enabled.png b/asset/tablesorter/images/forward_enabled.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e6b5384b8454ee7f44a8f7c75b0321b7eeb9b1 GIT binary patch literal 1380 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsVip+||I$+{MJu$=KP@(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1P0rUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZnqfWG!Lpb z1-Dy_aq86vIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@iW_)h2mVtrshNp{TNX4zB zKmY&RGjC-OW)@`(g)dh`10)R-NpU#bM1=1eo8Z2AYd)<-?^`_sqOFY@6XS7KM&8JXTA5$g^A9S z{TX;`xlCJF@2;-kt^WS)-(qj^YjbRh3Qo21zn9<7##PJs=)J=q?vtT6c$tqWSn$;S z{q^hJt*2*?^Szy4@bTi|;PVYm@{K=qh5oS|v0uoRWd7#=|NZ;-*VL7!+I+Ui=RzOdW2D@cF)|8@0kar@euUy>OYxL3%Wh|X{LVLRn7b4UH-Q)xXL zlsIOXI?k$WjNtJ4&-&^N(`qv`*KNBfVYRHPjKr+8GT t=fC*;><^O18kWptJjt-AJE?(znPJ1m)BPofdH;jTJx^CZmvv4FO#l_Q2A%)_ literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/forward_enabled_hover.png b/asset/tablesorter/images/forward_enabled_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..fc46c5ebf0524b72a509fe2d7c1bc74995cb8a9d GIT binary patch literal 1379 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|80+w{G(j&jGsVi#&A{2f&C=1($=KD<(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1OqgUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZns$AG!Lpb z1-Dx)aq86vIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@imN7BvVqjpr?&;zfQgJKk z&;S4S%v%{AKQQkRwI?VL9s)YsRaG&b6_ zgRo<91_J$Y%O?`e|&#$ZtS+eXp_f= zjUUrLb7!pi%4at>{rxttxB!poqO-MU1}Hz4_scgh+`O`|pzGU*Ppd<;SGk>1td!-8 z=;-~nzrMci*RP)sFMiM0pIiAYgm$R?>m2vx|wYgZ#kAH7}W-quPuJDiV$o>g2t#=I)c$y9~%y7A9 zTfgc1jk&Lj_4ZX)f0PV(p)9c9_0ar=AL>^e-n9Mw|Nr~<^YZ!qF*`48{dsWi)b|VZ zD%w*xPFz?Y(EM+~bAgn@|LT8!dGP4_dwn}*-YUka%$2Ws1@^aZs%Q9^A9It(GQY{> zGt)+aDgU^S%wM?fC!gsP`E`4^jM#4)q-B&8J6^t!zrwrDf%l)k#^S|Oq%QdIe*R^@ tLh*lxrsW37V+~Wv{w==9!pqEIz%cpgo%)U5J^Y|z&(qb2Z8_q literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/sort_asc.png b/asset/tablesorter/images/sort_asc.png new file mode 100644 index 0000000000000000000000000000000000000000..a88d7975fe9017e4e5f2289a94bd1ed66a5f59dc GIT binary patch literal 1118 zcmbVLO=#0l98awuV{uMt6P_}u4rcI3idKFP2SpU%ZJIE?RL`X zK?Oyo=*5GG2SxDYK=7akJqV&hrl{aWJa`y*5xh+1%i2y4V}gO?edPc9{r;a9vjc}) zn|Cxb4AYwFmvVG%_ui)U^y_4!ujsO!qzYuv8YUIR!Aw%KiWp=JrG#@>(I!s4#N7H->?w+cxsH2#GA};A>g8lyFDGPKh!5)vuP_{)}*83+N zJUBU!S0_i+E{*Lu1iGsNB``2iK-CyCU7?y_mv{xb_pUh>ESZqe1Y2{eAZLMSIT%EO zFrdOH1W^=3p>Qk~I{J+k#s5zQ@j{%aIA!l^GQjJ zqA1Uc2%!{8qBKfMNh#9DCnKS_*uZ8?mnf!+8@f8xtz#prVg=E`3bCBLWsNmDAX~PG z<(4fQh=UOzE2?gKXRkc9XeI3Er?HlHECVd%SI}3`hy1_du3@$R$r(qT;k@Sft63UX zv;)2Ea_iH>^6+4jPK-lGM{Zw37Tz>~~zlHzO61x51(V4jcaKrcIVDG$-d>)z}S|7f!xxYhfUE}Kj zug_h&HZN}go22$5Ym1}P8~vYNx7-~$TWFJ;_nh!wFYSAQJF{CCo=xpK8^7?iY1^!H haOA^1D_`VC7fU=jcT literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/sort_asc_disabled.png b/asset/tablesorter/images/sort_asc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..4e144cf0b1f786a9248a2998311e8109998d8a2d GIT binary patch literal 1050 zcmaJ=O-K|`93R^(@goeAz6hRU)S-61)?IaU({*Myml|8vh4x}JJM&z}b>>Yo&vx~s z*1>{0Sk$FMM28~iln?~vp$ zL+z1TilQ3g{c@7*P2Q^6L;g-8^nq-LaWstw(J;=d4x}PF%0Lh|)htXxRiC)>9(Gfd zk2X?ioL0_@8ZsHx!!QNYCTxo8?kU)+mV+2%VAin0^v_psXkh4J`eIPw6kCELM*pM( z2PX$o+GI}a)ajlxpt~Rv0TW^s6wEQp6$@dys4J4Qcg@nE2*J59y%|(mNdO5s5Cj>{ zuW=y`gm{Jzw6(Xlp9TWQb1WyYyx`~C#eg7k94LJ>@#g5mVp5Kkd=V>5k6>(zESt~g znS6jjPL}06J3BoMLGTlV-<`0qTJT$LYgs{tuI3mvHjo88MKy!QahN8NZl++`Te6m0 zDibLfTTpG5XE-mVGEhip#w2PB)JKi0I-PD8)*(7w)xTBHA4Yzu(Y*BKcijk8- zXslet#0bL39YHpb27^FRHN*1kB3@C%xaDHi(qLQ;(?o$W3|;IHBC-_Xc|nkPo{#bo zKE_Anh#c$_BEdk1ROZS^8#kea%Upe%D^%oqqhQ*^vkV>MD%4{RGC?tA(byrDwm?jZ z#$wTmdL^!2ITo%WmnFflUSt1hboq)*k9XV}TViYtKD5ZRJ7lb1H!ZJ`CviJ2M^c5A z%=*Sgk8hr8@-S*Kr`Ol~RJX(fddmmK4eR}O=#0l98WD1Hz^GK+C=e@fhgE~b#2$Ux^~T`1v5)mw1NlIe}zC z+ge9alrMQeN|SYi`>tC{zIG}!O_oO7k;UC8kBf>8sknx65F`zy2d1H-4fel=trX>@ z^-LCL<%6P%3`TJ=Ov$hao1$9VN|vJbLJV@SM>nJN{L>dS(6uOiBq(#Tm4F5Pz>p2Q zhq^NAP_G)%=(c^JwImV&17Zb~j6Ty5OHq1RS0sD)n5Dro1ouYi-$7;N6i6T&f*`~B zRW8JV5YO;|=5RQ?2M8R`v7Es2f}anI0YT(Au=3Evo2})=wA8uci&#;*fUzaAY_V8m ziU9`MJuDxIL|hF)@DqgJ88op{@|#XmML~j&YU>u(kqKNyC5HxZlqQk>PQkENWld+L zOr&6JNwHX-;oOueKw17j)G$`j4o<^A@%~fT$qZVMO+yC_*eYpUzR7iEi3uAj7}*(w z`YKgS6%a;F0a+l?9R#wX>ZWTi<7HV)nhsV>6(*%9O%xbi*F?TK!383rh#(|*p6}q} zd?z25;!?0(hzA2Li3(Rj>VN@FT;Xbexbdo7cN7eZc$T28pMYAYjSR4yvZz;&C0tc+ zg{xJMrKKvDCBd+6WB+P&<%mp=yImbyVyq56G|9BvWUP^I>ms=lb4e+lDSgg;Us`JO zKB6{wH+j~F#-A4FY3K3qm~Z6m@V6}oQ%8?p-E$dw`#0C$PJfmCV8)v}3>Ydha%`fZ zJk~G*M^A3LGk$Td;R`icF67R~`sBOHv)Hlqlc%$jy~9_oZJcNyWxkbb_O9u#|7hLF z-<-NMLzh3S0YA@8gd1Pt(Df|3@16Y-n=aSvsF@AkI`ioeFg>&H3bXU&vBnE6gIChkL+(Ey+0iB4Z$Eze7t_CX>Hq)$ literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/sort_desc.png b/asset/tablesorter/images/sort_desc.png new file mode 100644 index 0000000000000000000000000000000000000000..def071ed5afd264a036f6d9e75856366fd6ad153 GIT binary patch literal 1127 zcmbVMOK8+U7*1U&zKRu5sR)h{1;yRWWV^4}ShvZpU2*HWU2!iy(qy)cZ89;Lb+`3m zMbruv!GjkO!3qksP*5)lD)k}=Dp*ht-n@8G5m8XoN!zU+ih_Y;=AZe$?|)|~*Ri8v z(dtDU$2DZy)jV65`|pB!_H}d7Cv0h=sUqzpC0fy3%q0!dg+a#Bx^W(BM*oq=xP{{a zC9_bZ#q2IgCss)FbwX9kVQ7wPX{|b%-is;d!ri7V^Y8E8=YeU+{JuyQW*r6hnC$~D z?i}bS=mWia!r)uCftISo2rNuBP__DOPpZoN6tBeg{;|M=DHYl)^V3chvpJv;7lTL$ z26Y&PAc{gL+#HL=wg3?#C_qs_Vi3iouqZ(YW*(kdbB&UeSJN}Lm?ZN(lsb|iR4SEF zB^)Adw}29fgwG+0L8cM(`faLJgSNN6#-L(PcTI+l@K3y+Xf(g*^61+0|J+O6zN2mb?UNGh6GU@A{1+eF%d@N2(^XdVmhis(y25|iAr;gV=io5OsYy0 zB}Gv|2&GUGrBPB%s*yG^841Ug8a88lRI_zlvuiTDGuXsmv6A9qjS{y&NMEf3ay^6+ zuZK85>5PD^rkl1e`{kLAR>iJ)6dP%mSYRr@k~xQcDE=$%X{_--ITM&Og5Ml}G)wJ> zb)dhUZG9%p4iC23#JFrUCcmwHz{cugMoku~ue-kg{Mj0~%`FeCcz9jAdg}QET-kSG za`+2B_+lRTaeAVz>E`F1pN7h>B=BbGqcz13d%ywZR&4OjkNNrF_U}#EcXDGa@V52B z>JnIW7#s%CHi literal 0 HcmV?d00001 diff --git a/asset/tablesorter/images/sort_desc_disabled.png b/asset/tablesorter/images/sort_desc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..7824973cc60fc1841b16f2cb39323cefcdc3f942 GIT binary patch literal 1045 zcmaJ=&rj1(9IuWjVlWt@h#q(rlc~7%$2P_q>KN??ODrK{#&I!}_Kh{rzS=%m2N%F- zAW={L0VZBJnRrkSCK{q1NKA||(ZmA>6Hgw9o;Z-;>)3_|u*vIt-(X0AeGY5Bm`Mgoq{>2>Xkbiu%Ds= zw2?31f^tL9kQr8eOxQDR!ltPHq-U$zG{j&MP8pU+Z@qp?149?-TQP-IYzdZ(;duv+ z&5z`@`Drbo)5+_g-xG*{39$-1bH;K7Po%550y+EF3=OIfJT20DK^2ryARz~WSeOlI zY%dFXxiA-r#^dp8fM+?DVR?q*LtI>l@B+(%+D8*_j$RaUa;D~sSR!4**cKS3TrP*p zkuY+m7%q`W_!>MPB8ZS%v9RieEVsL^AVXJk3>zEB0=}X;iDt1#lSubcFztq{<<`nX z3dVS<&2VAXPpJ-6l>b9bvw?PT4(`W$ps<^-*pSIV7tJ~vX67YQ8ELa7v~ZoP?{i~^a{W;-ZQ@ymjxh)IjDt*2O<6Dwh=q$vY$VY; zc&J{Ds~-?cjVm3>Wk@iL-`IZ|UB4pJ;~yJiON_?gLyJtiL&kbxZhV_OiPfx}%6s1@ zcXoG^ffrPJ;LQ4(`t<(ickJ1j|E0&fC8lSh8sUh5lwUg=l~QoqsK t`nTanN|e2@a&yVMdhyj[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;eb&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&& +(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g= +a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('
    ')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m")[0];w=d[m+ +1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f= +1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k'):""===c?'':c+' ',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"""));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value, +g=0,e=c.length;g=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0, +a.aiDisplay.length);la(a,1);for(b=0;b").html(c).text()); +return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"), +"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g); +null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c'+i[1][c]+""}else{c=0;for(d=i.length;c'+i[c]+""}b+="";i=l.createElement("div");a.aanFeatures.l|| +(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;ca.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a, +b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart= +0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLengthh(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width= +q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML= +"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."): +""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth> +d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeightd.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d= +0,i=0,f=b.length,g,e;itd",b));j=N(a,f);for(f=d=0;fc)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1); +return 48>b||57/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b
    ')[0];l.body.appendChild(b);a.oBrowser.bScrollOversize= +100===h("#DT_BrowserTest",b)[0].offsetWidth?!0:!1;l.body.removeChild(b)}function Va(a){return function(){var b=[s(this[j.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return j.ext.oApi[a].apply(this,b)}}var U=/\[.*?\]$/,Wa=X.JSON?JSON.stringify:function(a){var b=typeof a;if("object"!==b||null===a)return"string"===b&&(a='"'+a+'"'),a+"";var c,d,e=[],f=h.isArray(a);for(c in a)d=a[c],b=typeof d,"string"===b?d='"'+d+'"':"object"===b&&null!==d&&(d=Wa(d)),e.push((f?"":'"'+c+'":')+d);return(f? +"[":"{")+e+(f?"]":"}")};this.$=function(a,b){var c,d,e=[],f;d=s(this[j.ext.iApiIndex]);var g=d.aoData,o=d.aiDisplay,k=d.aiDisplayMaster;b||(b={});b=h.extend({},{filter:"none",order:"current",page:"all"},b);if("current"==b.page){c=d._iDisplayStart;for(d=d.fnDisplayEnd();c=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)y(d),x(d);return g};this.fnDestroy=function(a){var b=s(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,i,f,a=a===n?!1:a;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);if(!a){i=0;for(f=b.aoColumns.length;itr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(h(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(h(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);h(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];P(b);h(T(b)).removeClass(b.asStripeClasses.join(" "));h("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc, +b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(h("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),h("th, td",b.nTHead).each(function(){var a=h("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();h(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);i=0;for(f=b.aoData.length;i=t(d);if(!m)for(e=a;et<"F"ip>')):h.extend(g.oClasses,j.ext.oStdClasses);h(this).addClass(g.oClasses.sTable);if(""!==g.oScroll.sX||""!==g.oScroll.sY)g.oScroll.iBarWidth=Qa();g.iInitDisplayStart===n&&(g.iInitDisplayStart=e.iDisplayStart, +g._iDisplayStart=e.iDisplayStart);e.bStateSave&&(g.oFeatures.bStateSave=!0,Sa(g,e),z(g,"aoDrawCallback",ra,"state_save"));null!==e.iDeferLoading&&(g.bDeferLoading=!0,a=h.isArray(e.iDeferLoading),g._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,g._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(g.oLanguage.sUrl=e.oLanguage.sUrl,h.getJSON(g.oLanguage.sUrl,null,function(a){pa(a);h.extend(true,g.oLanguage,e.oLanguage,a);ba(g)}),i=!0):h.extend(!0, +g.oLanguage,e.oLanguage);null===e.asStripeClasses&&(g.asStripeClasses=[g.oClasses.sStripeOdd,g.oClasses.sStripeEven]);b=g.asStripeClasses.length;g.asDestroyStripes=[];if(b){c=!1;d=h(this).children("tbody").children("tr:lt("+b+")");for(a=0;a=g.aoColumns.length&&(g.aaSorting[a][0]=0);var k=g.aoColumns[g.aaSorting[a][0]];g.aaSorting[a][2]===n&&(g.aaSorting[a][2]=0);e.aaSorting===n&&g.saved_aaSorting===n&&(g.aaSorting[a][1]= +k.asSorting[0]);c=0;for(d=k.asSorting.length;c=parseInt(n,10)};j.fnIsDataTable=function(e){for(var h=j.settings,m=0;me)return e;for(var h=e+"",e=h.split(""),j="",h=h.length,k=0;k'+k.sPrevious+''+k.sNext+"":'';h(j).append(k);var l=h("a",j), +k=l[0],l=l[1];e.oApi._fnBindAction(k,{action:"previous"},n);e.oApi._fnBindAction(l,{action:"next"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",l.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),l.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var h=e.oClasses,j=e.aanFeatures.p,k,l=0,n=j.length;l'+k.sFirst+''+k.sPrevious+''+k.sNext+''+k.sLast+"");var t=h("a",j),k=t[0],l=t[1],r=t[2],t=t[3];e.oApi._fnBindAction(k,{action:"first"},n);e.oApi._fnBindAction(l,{action:"previous"},n);e.oApi._fnBindAction(r,{action:"next"},n);e.oApi._fnBindAction(t,{action:"last"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",r.id=e.sTableId+"_next",t.id=e.sTableId+"_last")}, +fnUpdate:function(e,o){if(e.aanFeatures.p){var m=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(m/2),l=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),n=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,t="",r,B=e.oClasses,u,M=e.aanFeatures.p,L=function(h){e.oApi._fnBindAction(this,{page:h+r-1},function(h){e.oApi._fnPageChange(e,h.data.page);o(e);h.preventDefault()})};-1===e._iDisplayLength?n=k=r=1:l=l-k?(r=l-m+1,k=l):(r=n-Math.ceil(m/2)+1,k=r+m-1);for(m=r;m<=k;m++)t+= +n!==m?''+e.fnFormatNumber(m)+"":''+e.fnFormatNumber(m)+"";m=0;for(k=M.length;mh?1:0},"string-desc":function(e,h){return eh?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,h){return eh?1:0},"html-desc":function(e,h){return e< +h?1:e>h?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");return e},"date-asc":function(e,h){return e-h},"date-desc":function(e,h){return h-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,h){return e-h},"numeric-desc":function(e,h){return h-e}});h.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var h,j=!1;h=e.charAt(0);if(-1=="0123456789-".indexOf(h))return null; +for(var k=1;k")?"html":null}]);h.fn.DataTable=j;h.fn.dataTable=j;h.fn.dataTableSettings=j.settings;h.fn.dataTableExt=j.ext};"function"===typeof define&&define.amd?define(["jquery"],L):jQuery&&!jQuery.fn.dataTable&& +L(jQuery)})(window,document); diff --git a/asset/tablesorter/jquery.js b/asset/tablesorter/jquery.js new file mode 100644 index 0000000..63174a0 --- /dev/null +++ b/asset/tablesorter/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&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 p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(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 bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(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 bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
    ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.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=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/everseiko.zip b/everseiko.zip new file mode 100644 index 0000000000000000000000000000000000000000..7416f60036dd212100e8a13ef221db1c8e0d9d00 GIT binary patch literal 863523 zcmce-bChMvvNu|`ZQHi3F59-vF59+kblJ9TySi+@-sj%;?fad(&-?SOF>=kh*2v75 zGcrTJh?JKG27v!aQHE%dLO|Nescb2YHHx3(}caJI0srI-KH6Xnl;5CHOA5`v4W zC2R11e!>1}sQ=cJ&fM9+$jHRW$w_jmQdxp}d`3lLatsjQuNnTC7Sg}XU}RuqZt`yw z32|2~|6hvO|JeWk(3Sq*bpPwg6Zu^E_tnS?wEm2D{L^s$aUKg>V-xp3li66aP6?7WvRVRlo zV)!r0JBw{#_#s{MMV2$NFAhskogACj5UMVBq3xXKiO-OlNOy-=%6}x50++#q$}VB`+X}AZh+|N4UY@ zZW94FYG`!N2P3L5J3mGw6OSdigu090!#yvFI`TuI6|X0)DlY*|8os8n;hta|DH}LHNy8{P=Q9cAWDKlf z09_;fgE!ZdePL|kg1;wY%7YkpQIW6}PFh3Sxz5&j%?~?kWZBt|)*$ zX0d4AF3ApB#WSs!V83QVj_gU(&Ct7~o93ksS#|y*^f%VUvPsfuZpwcoxN~eP9TsUHeRLi)p<*`M1BNn4gFxv~zL{=!_|_#POC@6^7Mc%rZ7M0ay?MiR zkvF4%T~!;FwMIPyJVL%UvNiLP(a__uW&Iwl8~kFEWzOL-Gv9w=T7CetExo^}eEE`y zrRCST^(i1CQ13@(?dp0B9l@|2jdqt?GGtVi#C)@8@R(IN_o!pbgCfe_r(O+9>3EW7J$ zwTHeQo;=OOr~<<)+O7W%sQ>zE=}lR56TFzt=CsFjh9)kdZ@2e(SGJ-A&!lHsk-6F_ z9#m@@h5W^g22#QEQ9X%0?&Nw&-r6_((AAQlhI9 z+EYv#ZQNnL!%W~qAeETUv8Ux+E0P~IsY1m9u>(YA=5&N!CYa2*BuWZc6c>zCJaDvG z;*hTjnn4`aDc{zmR)xcs zYwS*H8ya}K>wNQO%R;8~L=}1in35?B0w_x3+yIb{qOWe4vsOMCq_xT_lauimXxY%Kz^Kbwo5cHW6hQp? zt|66pKli}UheVKXsI z((Td|XTXmv!_aDU#QhOT-xo%_=ukCw^f|DSwkZ7pzN)BU#?k!niux$|z`Z5W%{+|( z8{gIXUk$Sks3IH?vwiFJ%~pHkYcl+eMpmxjh%wCYZOoRcCFODcG@scfqhZKSCd!1o z7@N*pQFZ3jC&v7{d+UCbM<|@2L6$Jr`b;EC^ZB5uTq@QGgsxe(DJkE@9Z8E>v@+5oWBACJ4X zE$i&0oJi03>5`-*LVWX+#Q5YF$M28N9p5XwA(|sA z(reUboP4|n>W?*&g|jdV%((L(J;2dLEPGLAzz)n9kqZ-vnUUQXdb-hrhsW*wSmCjO z;T*Zz1Ayf0W}kcJ-i}US06t}EcJBiVW9H7Rt(ZQyLot#o5s~#I#VGxzTRiWHF4+_QGhAPTQ0OjO>6M)Wa}JE%o0*~gPdM!D@PnII;1g%^ zZNE}u(&fbcr@NHceFDGVK7pf4jae&obuY9ux;9YK>8$);qBusJOX^SuV375wjfeIT zVTlrclsb~}3G?;{#13FMU0&Fp3}}Gh^~tUjEO<_99;XfEn(2G7j+9r7Ia5XVa+(I* zu~rs|{CM4VTX!>5GbkyT9L%{MWh3~whaF`7V1eCKd|9go1}Q;vrq&)Z#70V}bQUVHRtw>SdZLu`*+Rx7 z5}8Dx8IR5GOpKTy_BqsyKc~b||J+HhE2Na97d&P^e%D*2H?Z6YcqgM==Gp!ftlk(; zT;eGejBd9Uq(tOunRUM-`t4VZPgdxV&BOkFwfJ_#2p5CvI@G#`J)nzLOn)-JMXMEW z?vj$*k8%D8ECk{c9f@pp-5B8@f^1+BvfsyS>bHJUl6udzt<&AlOf`_ASHH66MR%Tc>0$+%8|vis zHDnZLVp;6-OZzKh#0!(gmH}X&vQJXS{d2ThJNwOneSg=ah&ml2?lK4VMb%+(`n}vd zKRJX$H=?Img2Ci)gM=Rijj*EyP?6vi zp{F2NS(JWa<(n;4DThzozPJV%p%j*tkC2N^^QSXePk^d?9;IIAdLJKjy`;y8xIUX) zr_W3(EKKX|B+$LQ4$v1OcKiE3r9f@$Y(I&A-DWkfv4_gH%8NLQiJZl-YK^hNft^(Z z3GIvedK1`!%WtZ8it^&Z{A@i}l0PI=G?WJJP-!p3`MH3|?az(`}(|Z1(qjx&7gQ7dbPtHnVs|Ix+&oOu86=NDT@A=1BM8J>l(yyDs z);D`@j2JoFVex`9^LtOUv1daP6sSO0SF8ai0VoV7(&$PD0Cid6Cu>||F$#8Ck4GG4 z984ZuIj#LwH3}4zqj{No;Kn5&pbV{X5VW?85j8qjRbF{w<&Q%)ZHsGuTL-NkOXifb zLKzCNJqW$2o3D=i9ShD(2d3WNvX{fopMwB?^O!wZk;)Bq@x4GVx~8PXu05;!1P~V% zZ>Di+h%K2oe09mOE-`C>vJmMPkNCW-SD7LrwPwUwm?HO^;t$4%gAqqit+FW&GKZWp zmtr3o#^3d4a`DJP()te6B-azK0`c{g5-3aIaB(;g7_P5xN9RMK4n|;z1_n4+QAEx5 z++G%33T{;H*KozS>+sj&rTw94+)~AF9j2kqSRixbK9>xgEkkX4=Kc;wG$%G)Z1P>z;Eg`YL64V|g-Kc-v_#^pe7u2a!zH!!@K|qQDk25#y-gkw@v0C=N5}I1~F?6gM9(3F<9~kGtopmZ( z9%>@ja2=srZaNgQaOZkEqTEs?z=CF%Y|I++Ri{o+f(M8&QZu_fS9>E?6YSXH1shhn z&J6l?*kAmA$I5@&R^|p!n$e4s9hO zpJwm^Bo7yrTMd+fG*WGiU^7j_)~Bq;U$R6G#_qUigH*4EvW!Y=ZaK|xKEDj(^Q(x0 z5;%qJ(i*2p2Wt%S#nvpmntM#|W7rex4A!t1&*$0e2gfG^(}8G0cha~7Vn)h&bsgrp zeP0dbZ1ZM~A^BIrkYzWr(Q2Q=TuzL~%{B-`%41Gi5CzI>P3BR``%}n&B%Rm%GMMB1 z_B#3zFBJ<*4b7%9? zG{k7aqDvWtT*W=K6CXHxYN3*jaoHCc&(v1K`wfPOY_y$uO!cE5B^T+(f(f)-y z=jXCZ{V=;gf?uHuN~7_xh7qIg~>|Gel^@qK9S>VbE!?AP@&7o-Z+0LbN30YT6R z*$$jtr;~4fj@9Z4T*h_&`9VZq`(DU50#KSdu(#{%{B`U709gZGIQM!p^(ePtnnVq+ zRE&rwWi?s_DTE2Z88Cv7lJIVTjkd?WFwW*4gf56jVzcHx9LC?avo3`SlJKyFZ}E0S zj~a#%cIi3m;*GRH&(IgfCR+SoyhBh}DM zl^wTIBvYMonuZWM2UaN0a&Xhfl{BV6x0yy#=r|Zl1Z^y5RgREs5S*4OW)ct_3`cUv z4ds}iQ9a}%ZjnCvj(_zM6`ESur+`xC_6LWjD-$wqSE4TB59$?Cm&BW`X7$8mC$b2$ z1)=1X5qWB&5m3p_!b;n#VF{tF-PY}serbBIddE@azUxoCvQy#l!trBLnKOY?QuJnv zSj~o(R2gmSrJY>UB6(XkuN==&@|{kWOJQ6Cks9 zd0DDk_UW)NIiyzAkPjA^sfg{&$Wj3uqnqBNG^c72Xs_-PR)#wzxvpZ?0JA|p)5g?& zd=k>(KLRu(bDp3*Xn;H-;pp;1;br_AG}roslKIuZdD)|$s}8rLYJzy!Y|vTCV1;%c zy#ON-PhREGV>FT@(lA4klp|@D#)gSPo~@!{KJ!#IsgJ6#RpP?77$Z6wX^j2^MM_K$ z%$tsiB7cd$RUu17-I+$Cb*D|~!hBxnovS<4P1Uf25T7p@Ne4GggBlZF0yqU8GhxBq z)pI`}YQahdVeMLvO#ZZoTUM&BXU*#@+Q$}avx;D|gj z!DrU0iOuO}6Wmd2Q`2*$JJv|GYHcYkuF*w(mbY$Sk9Cy$9WrC*B42lC6}X2GmzA6U zd3d$}$m!z^TU~z1#CJ`lOlVT{=0(iKoG zKO6*(s0BF{>oV1=jeybOGWai8i>Ucff@s25D8pP{Kgk7qH;QOVaX%&*z25+=Wa^+; zGjXCSvCK`tJF_KQ9c+uo`M(us>`cXvyaaXt5_(SD9c!CHzYjQ1Z!e%TMdx?|Y-2&> zDj!yf$4f1jHyU2h|JJd8S$z?upY#@he{yvo|5?Y{8995{oBYe@XD8{&^)sLhTjYGnz3O$pdWbbWae3-zKEG)PmwSnI#meHsf%Di6l+rw2ofMq%RhE&cfT4YoZAed zI{ObYuB{&>c+8p>ulQdSD3)&kFP2B?hHRgB!y~D!3crQ-x||#Xx>Q!?0gP6D;~N4T zl&!%R79&|!vwIUIYfdPPgi<&MKJHD%PiCc?Rt^{|R_fk&^}@Xb8A-YQX&s9bb&#uR z)-O|k=eHmu5pA-|CdplYJGRy6DjJLJsJv*9rXCiKOaUeAH?k7un_;*d%Fh42O8gx;HLibhk&l0T zGm?My%}nhaO)Si8^^D979RIac)yY~)I4TGux!H0KRSlMY^OGG|v{B}Z%8f9T(t1@6 zZYj818Cw~+GId|@n?eLYdq1HepFtp61dxFJ<&zh>POLo8-iq$x*tbeAcY5U9X3lbQ zRAfjWNR{+! z(^aUds8c1|iFowfBGa4SsT0HtfZ)rwVRv@GjB~z1Y zV30pyBB7R8tmcn{s>DsUv8P{1m{_DKOV>9I(9n_NotJ($R1 zo(DRMWG))ShNvnC52}OK2Yji!BAvegHA|f~RrTW{<@SE<*slEsK9l!n?;T^%)%N>Xd)Ggdql!Y67 zBu{Nu*1pA@l+poZ6Sy0+o3>vCF~`rV&u91Njh}hAxzX&wEb?sPuHX$r6fAQ<25tpr znwl-skQe?Nz#HWQ^9{la-6V!P3M;oSy}s=2+h`Zu3Aj5D4`>eJTcLcW6&4RQ3n~|Q z4mdvmeT4mwAg|r`UC)h6!5bF=)DJex+B8!~t3PT+0e z>%wMeW;kX@W>{wE1F)O+ES?~~fS-`t0Q_Kffo^?In(*=)f$4tf0re}a;0L-_uACOo zzJRW@-x{ZojW#t_-l58uU?=4DTf3WoUfWvQUh5P+Uwqf7?qX3dAs>F&roi;MofhP4 zZE0+4t~=9#y&T*&!9>|(@=;G{5r^U>=QG1yFws)-&WyXQyLv~ra0&XcR#i#}=&qugWj}FwB{b(u7?U7#%*~I^Ps-~`g>Eu=R4;4CxV5L2 z(e#Q}YOg<@a|kezyGcU+Y5Zapot$~8I?ALnjiTAvz1P1s7Pr^P>2Ml{+b2t)^*je|pH!k@v{WhiVv!1`T-M`n5{D-XV z|8E5(f7j!1JIbRD{#i$=KM~1)h>vY7%pCt!%JZ*+kR(03g+Hcphx(CwGgQ)|vS|-< zRURQ*0875U`v*kZ?GGo?6}Tr@LL~g03lbYHk|#g50*de7UNN8C^?E(!<4`PU#tJhD zEo)nzi8edrPA?yzH{`c8uZIGOBUyxpIaFZDCm28!M%sZ~={*^;^Fz*eRM~KdL6$UF}Y!z%U9hv}1HEegNfHpgXXzZk#AO3in zYQP#|mHwa^z@(#6JQN%_k80U_MA@=*j%Lv7JLIL!c7f)1s5QG}9bH<`YiEZVr#U~= z#qbXIIO}Ysp$N=y>x7Zw#8JeJb`|Tj5ug(Cgt0N;&C0yYZ}LxH-q!m;Bd_k>iW)oF zA{cM1;dnU2+Q8q05nwTqmqc1>inJ$s75}6_2cSE|iLqEZ!gN1U-Ps~0e3yJ_GRv@; z5zBtUkP7TYiR}>XG@~9hOm0XMT+NEw!a^Evtdv(UB|ST+60IhikhMyi^DwUQDxbom z5H+Snj$Aiclf9K8IdL)bTYe<_{+{idVase)=z|(wjw36TF#ew1jrhvNO4ZxEM6+1g zTYd!gg{*wA#m_D z6CjnGC3)bG{9APCvUy!9zFo0J(_$e~7m1^JEPycNmSgVg1=OqV79$qN#tGSJI}{iP zPVasLzd{+J9!IADA0aqPMSwn$f5*4`{o(7Y*0@7-mdPpogBa0-6(NwNJe>&w8Ay|O zvW*AeN3$LK+R`z#RL}Q}=j+Sf0dD*E^}^Q4_tcTk7|S>&xQMX{L#6c&buNz3?GaSa98Hk%9Kj; z+Q%u6)kBTl`5h5u?)u^W)-^h$Y6NotY@!MogCxGXiqQM<$)Tr{!8cNY3=WARg-le% zk>7cV@H-n4aP^qx2xOL}eCsfn`MQ2Lc(!&So_fjv7%8K^qK#$mzOofnJ2F>r3IPAo z`l8Et3o9*dk1&s6MEhmt@8U~`2R8dT0S)e&T%V}2Stm=bcDzGUUC8dF3juS&temDj z8>Rem9%Z`QkUm$))*6lCGaPFr6)9pD%H)$q?Gw3y@m~4q75{``9z~ugzhh~Cr+FIP zU*-mE&$UHtpJZ&4vGZ1SE=g$dY}N7L0Q_U%lB(&!U_iYc+&qm$O#9ovG5aJz98`0ai(*Wie5uAfdsn%tbV6BaB3LJpgZmWZ zvbUJ&750N+rDt>c8H-rN=9H5OpG|4qJCIlcYF)}_0?Jd~GyG2Q3m=GWZ^i;R4;g2# zq+88MNveNcVC`V#(A|}<`o|d2Xfe-K&=tO4IeW4UL zu~g;hC~1P_8;xXn&(sGOOQ3a7CvzdZ#*IxQh4I{Wq%){)M3m&C)~6brxgi|@^72_I z1st%^>;ipw;I%B2tT3AUuimqyQkJkH%gZVjbL2az;byVKvi%i@oz#Y#^%HGH$B zvBU&jxvjRmE?@?7!ZSU*Hx|=F3EDwfD5G1*^843ic7d48I>kl;T!yH;iq03)eY*PP zMBz~n;vY^+T#xT=Ire-cU4|~@5B`+Hxu7beTJ&Mo&T+`7ZNK>#NR;TZ3N~OgQy}_M za_ibRp>MvyCDm|9K}YZ@O*E3pql_5oVyZ8|K?jgY1=1k3OBjIf@04o{a^KFXY725A*ehWHfMA9)tw9cLclX3HpF338B+m zPKk$%kJ^Zx23A@4HSR@aZ5I~>jE7LBHuZ{?&g0pESQmHI*-dBP8{_+3!A@5Q-DIm7 zjttlR`_-hC;v)OA ztqqfnl(rIN4VZO4TK4{I2er9o{^`>6*I3Q0j_8&g@K$EG*U>ce)Ev!u({{@i63rYhsA_UJ|)ndqP z(6zRy32IWfBTzQFg^wA#5ljVMdImF}gdihPRhQxsAn$P}sfV*_&nyX4KCZJrnrbD09gvvnD?N?nZ~0rA>H z3iUSn9+1GK0^~`7G0QOq23=4{0VqYBps&EAsPo~fGjf6T`=xykp+@3${c6?4Z@Os(o z0c!j7jd(Kx?+(@;KhA$2OMAFOxZ5oVdPwS93uF_V>%W6YSw$fxIkDtX!plW^YV!12 z>%kjs(M=oNK0Y0P+}-EI+i7Cw*TeN0MAQ|tf@HZ=%>YiS+J zc$x+ovLguRsHiHE_>8UitEh$*vys|PBYINriSB;eGZ-(>(IwAizeXjKD|KV)>5*aC z@F%aHcc$-nevaNXx=ujaK`9WGL}2T{2U}HbTz@u--QC1q@n28u>Ccn~5Ic5is9+Mb^&5@+*rqk!fZ+naa7^+kCqZVlyhsa@)!~JGd@cKn>AsOJ z;v0h@US3u<(l^nFOjJS6U|J1~^?;U*OM6U*ulnc!^voMaF0Vpmhnu_m4)G>hXK7~n z`+wl{#0r>2@>U@>t9c8eg$rQfo`?J8Zf`uWRi)=XF+p6eP ze}!E7e&a?)HKPi#?{?;6Y#eoBx>3gVQIGGUE}pz<>=#Zh@gG z6ew=MLDW}BJ2Oppz7bWif9mg|qIXnsr7f$|n#vc=e-%&AoI3;5Pz# z6Cnw)dZ=i@t||=nJUFE+Butnd?vt3`HZ|^D0&NYteITT zuc;7gN^;|EQFkjeK8hQGEI+PfT=L$E{n}4U2D;Z)sa#qy5Z#`MY}Bo;s7MPGRhWEy zRJUaGk?m}%(oc(73xMd*L^bK!N}}lMp)?I`Sm@kw`Ha{Q6uUsN%yuFD^J7b3|i`OXk!3avTt>SIRE)f%$WRezleM=YY{1AY^Sg z=9BV;lPhiRQe8^GgXFtRzW2Kf5{9(1y14(*U~44KjU8p?cKEJxEcI}TRyc>)U7Ny< zd}&jRQ~PLf4_q}cTLfVrgCn4@$#D0Es)hf#VQ`*MbT!wb0~2~adPP=~z1}>V1~S$2 zRjNl@*FJCYrQ;7+y98X9cyGf}kf><3K8CybF~~419(IRpI;2FVTm(=~X7)!eQxc1N z7$`p2uZnM4XC=Etk)rDdPPrcma%`V96Z8b%`@)K3Vs{u&1NYPTZHx{==wpGhkiksD z^Vv%1Zkv*OZDmPmc$zMleMQBw6DQiny98;AtD^Y#bZ;*yk-E$KIro@}NBTGG#*8?v zM%H!Cv{@qsgnC*Gl<08XV~U}orCqM>77A`JJa$ERbF;VWq#4|N2Pk2{F4__BrqH*V zt=V3VGP{({`P5m5l5dL;{fR0Meb$DH@^=rp#H=Zm?)btCk>K^40xE*F_8_SV0Gzw} z5%AhZfa1#G#76$t2ro#0Ej||^cNW^uPN&md#o8*eT}rU&P<}e1A%Zurb&kvs*A*Bq z;C~yszXad>ir_#V8~|YH&-oIfe-?ZfClg0K12dEVPWo1>>o{$+qWZ-A1g#i@NsOZP z=yEY_xojpLYsl8oQcZPCxReGbAw)!kU;v=dO8+cKnACkmsF27H?VeY6HP~n6>|=- z40%)>JqMADhx7?xppOcbGIqrPUHgOB)u54Dga#}R!hlQ9KUIp_S4r)gJst;LQ6n}PTLI_SrD4aPqiG4|bhX4m4-A~{+Q z*X5xW7I*2$I2>{Voqo8N8>=}!$u*2F>>)S*f&MN_=bELB!_~IxwoiWFyQ0nGc$oZ5 zNf9h0w|fS65+aQ6Uwwh2!twm`*z{SNC6|C0WJ(b!p}gO!1_q}zwLWr{|46e8NnOkX z`K`xg)CqKq;&}VoB$B5biw=cF20KQvudWCR1v4DP2x$s)g@ayF%w5-&5s!0XRYO2@ zpjYf#NTw_*%ndC_ozA~COIC)WHX$*F`eMPnfc<_UbT=Lu7t~(N8HayhmLd8fA>_)k zztHs=Y#3Ip)8BRFSLmLtJvQD{|H()o0L>smQ#Iuczn z-h-|yZNBAefyJP%)$O!@0R?R&4 z<+{RnjC7S!$wuPYY}Vi9TyrfdLFw;k4{Re5bK~zYY6N+ZN;$8_VrrAt}JErn0X=N67ZKgM=bQR*gZ3}-FxfzrBuqXb+ zfy%SS@XK$yT;|4IYIam&Pm&0LHkUbR4Z}dh*il6>C(P&sNe*8@Q!WP_4MimJa`+0d zu#C1dmhRJ@v+` zBxp7*w7l$7g8uSRxB%M>rcLf{_SPC}U(G1y2h<#o|KT-^prWFf6=(pO7lORctdCKhYP z*2^28_S#lCL1fDp10TO}#4-j$$#74v=4;GiyP3E5nJgU3DBmoZlG~5rt?XJW)9IGx z-)`@#{pL-NiV-(r7c*Re&p_iZEY`R#A;2bH<8SvUitZi+&@X0DR(eWmLaYR3+uP~(ey$If)nd$<PGz&ir9JTEzMz;>(uul%LG7Mr*n2VMx#AXNB@Av> zE;_Z#om@ulb`(UQJ^m`lLVf*JP=c3ccE#nPyUc5!a1E^zT)fSh)5FTuk8v6UxhJ*G zcTeKrn>ZeVo`7-%u0hr)q;c?*x;&*>?w1tBC0%hqrd#^^lFJR17G%BQAj1|#q7{Qc z6l&~ChcjD@#88HPNILkEW@JRcqDGf#q%>lUhc5>RwqP|sVgum~x^dBRPcs<3hGDT& zIDUF$n-?1p%rfA}z-^O6fuq@^K#mdtmwx>~!+pz0!PU;?m zIGuCYi5~K-y~C492n6``Cii>8v_iKN;;)|VXZ&sY)j&63h;^wyYBJ28zZtg$gz^db2DIQuFlZ9vVeb3Z^h1<{s*9Wg`^&7(%oTkMH z0VJVh9Ocnr>AS|%eKw8TO<;X7VnCQ%_J_$Wn1}ytLT1C*(PB0Y{Dtt;*Cl}TDv7R+ z?=KlYy0~COwSa{?>R(0Uq?WVV5q$yBeM7GH&+)&4v{*WmK^;Q^(^tDCSH_fugqEOZ zVK|E{Z$P9N>sdXd#}@jCfm}EYq@4E9N)tG7(k$)+Wh@w3B7^Hu8ns%Jk9=gr$(3mr zlHOdTqWz?5Wy2M(F}OJG8;+Y1kJFAyH#4K*VeA>`MX2ukfcW@Yv1p#-N*wjn(kjE; z@-R@l7^07fRA?`RbtU8MJ%KRgFs(IKJ+0kJDAUifEibT>gt$F;u$n-Bfu`tf?LjW| zE}Rp!CRZHzv}@G3TNUd6Mzd~LmNv2MdQ4*~9(L@Zp*I&yQW$4CC+ze%w()<4qJ${S z*kd`MO6Ftl=`@w?a>?TH;i^#eiNo?-IIm`Gzl5)x(iy*lLMLsdUCjN8Q*^QCDQMnx z__fDqHB}l+opM~g*LXS%tM5x!d6>tVm@@P_r;KzpQ_Ssz@j@L7G(Fwpf<)(iip zKM(%NT6E>dsf6;hxoW8u-r%4w?JW8cAtIkp8NuOI%m@>9)_G-mR1I6oE~&a9-_wq2 z)kUk_+}&)rFNpE*BQ3~*<4m)z?*$1rJ%31J#|8H{XN}Qe^W!%jc_$;Cq#kd{BnQ?z zxm!Qgg1SZeX}?BQa;faVsD(%qm5qRFPte(*E?-!AmQpGXC1#up_U8UVn9 z?;o>5|3_s1q~~q^!r+#){u~qLK>GR(^a|hE>vw459h1c(dBGLg<^0_2X0u?^;Kc#r zPay3)DVCxg?wEP;*n_V($S#?5WLj$u^qcLNM|hfN0JA&I2G$6}d*^*w%RNL~u19xL*{#{ug@b!9Q-0T0T+~ZIlOxN%t4n*N$c5K5n;jT$Ky#t zS5vP}2N;4Aisr(wz$kq4Be6Q=kszsC2FPCPXY$*9r_ z6~gm<EWE<%eM0))i?}ovcb_Cy`4T3DvY~yWR$VW%eLGBmc zcM~f!<)VZU_deC}IcXfT=nRgvpG)#=uQcLUs&$m`!-NXOeg#^!3K+o97Jl>y0k%!lX1Kv+U==fxyn|uYgTxKbkY1dS$lE4Pxfdm}))vRuChSf+p zb(IWfEPgW}Va9B&LVCcNIr||O98aNv>hAvb^szthA^{7%Z-2}g*oDNs9fV8$yN~R* zKePU9Uy)@dzc{1mrU)k`Rnhn`g98kXW{shup^n)MpjYFMOjs3kFA@Wvbk44vshU*! zqDNlE6^`WyQ-EOf&-X>3o~i_yR4zh!COX-*Un8W&kH<1|0TSF>z?SpmlwwXANgnt` zdEw`qz*PWV(>X}DLa+enpvJcY1Dz1UiYb&Zi@wUNW>hnhIP-_c4|)tSeUU8wGvX%D zFZ6nb3UENS4u^}L*19m0#eQu={+Lk+lrXC%Z zol3kZ zbDLk><*Qjo~(LYX(^4_1Co zvS#(xM7pEh;yJxK7JP2xKh1dt|1t>XIg`rfq^wvV6Lpy`k|3s$NgT~hjK<#%U~rT= zZw5`rRW=R6syR+VTFPQ-lqpRrJ69HyZPa>oUY#o)Aj>^9pQ2Nc{3WhD{~IBh!gqA9 zx5hjnrG& zC_q*PVRzWolS^06Kg*f`fPZwPw)_2A!!a+GqUgGo^zhZ*s>CoGpC7C zr{A4a#rzf?-IAtqc?YAeV#R_%<2%d#Xknssxiz>lNQecMQ6dv=1cKCvSvSM1aV%Zj z)gKN)=fX>v5n4Y+q5t}!3aqLS9fVALCXBC3Jr+Ub-fo`7a_w`wNW)TT$O5OOY#(h& zW0vidrp~IQk*D#LsV(CZV~jUQU*eL=IZEAkh-P8M7*~9Npd$g6D?meDvYa%+z#iBq zNBpUY*^B-EA?_Q)G;5M=%eHOXHoM$q+qSFAwrzEpU3Qmk+qQk{o0)rNPT#rn^PFGr z`y=Cdc4n@O9kFsnY)3Fu+(v?>-iUfqaix2+b!%lq-!c^td*2;2=oFkh3N#vLdmF7q z$?*LO(tJrm@p!0L1V^9*DvO20a3z^435~8hL(3+0$0n^93v*~b@FEUN>O+nKfMd<% z34>-URzW=@R0+n6&;yZ#l)Iz{95VUSaVre%LaJiiDu;}VI6W2SArEtEMEoml?Fbsv z!n-vIc9*&P*=T!nun~F%m%Y{r{)D7;`=<|(xXnj$>x>v@r?fcSQ{7^?P1xE9&Vsgb zzSb%$v_2cbHqQc?m9mNkOStKW(FzFLqS$1F=~-&0`fddU2g8ha|DSXiO6S**R9 zDmY_yr|~O(p#^74Q~cUmT#_|j?=kP!y0FfI5Q)vWtj>bUW9}1aU77h+pVT+^R~Mj; z_e#vWhpyz`s!!Z$ezr4Kn0;B4UO}IIl;5~sJw9adD169WK4cpYF85BKZy)d}{Cq6n zW-l&!wx9AGIBd4<+Id5EJ?-3{zH?eFkGh4dI=Z>R!{J*n-f5KOHT~ecyO4)hd=uc5 zuFdMrYhn$dv^k9ZV1E(J#_EtVX}kB|WzS^n(~~QG3%*=or4UeUZXacfjuW)GhbMmV zu{rpLv+DZPZyTpKO$4w0ev(4cy-!b(wRq{Rt}d<(iqT6GXM$AoK0q)2>Bn^wfch+W z`}TITn1-5K$4!W9*~D6jB{k(@sMxCk)S#KcvHuI1y1|tpdyw6GDeEf4TrW}*{m66y+Lf1v7+O&FltmQz> zAj1m1T|sdCt^DJ>0f0%;(^<{tH$@g~2|SMRUg5R|D}RgA+7N99<)Sgf0uwC9a2Nq+ z97)XbpzTb=XT?wh-3X2>m@Z=VfSO4jx zy(2v4;oPd>@1r!+xfS!>NtsH1#`R#VWYG47T-+{YlM3qxn$qvq+L%o<>ag7!fxo;8 zDHs29&vVYT5ViHmN) zWgf|Y+_g(L4S5Cgr{2l)#;^daSL>9%QJm|PrwxI-)5qWO$|&@C&%T19h4ck{u9RF> ze`S{xCTeY#K*o<%;vir?&iBk z9$&w``zK|7ekNElF|Jq|>`(UiQ?wGe{0w>k%Gf@o7gUO>t2{ZW#>5F~@FNu}84Kt5 zrqQXl>+rm%kYvgH28(b<8Tj{_gf`oMbOMKFlDXSiQZRc))vFv2(udat* zPvcN+6)MXQiL z7wE;swQkNCd%afZc1Ax_jf&*!%+x_dN=6-b!AK}f*4mJH%NzPk@c(?8K9MRzB z1M4{I#DTw-0hW2mR@&5|#|A)0`u*RQ4-m^IR0beOU&{t&)!GB2k z|6=d|mUXCFTVjhNe9#1Z_L5*cfGCLa-$_|%L(usNeBH-C2ty1W*vM))G*P=eo`EcW z@-nwQ7N^v&#|se$lCJaI@=cz-oZQ>Aar2K-ALG1jPXT#fmq3FrUe;L_bg(K1J$$^u z9LZGIO}D6u2@eg2md|Y_E_ZPr@J(ImQ7p2WF9p%V4HG$-)4L=#pzEs8yrtjm=gA#u6&G4 zQDaQq*=3R~r&1=YAhmjNM@GIrEEjtXztFDyiVm@fmZp%y6T+v~fkUNUjUqw`V%l_7 zAD_!Auu8=WyRk05VNSrD;)gfe_A`5OW4tqG3yNr$qxwz}L-t!KI-4s#8=S%6mS|6K?Ptd~93i=thdz+yyO8g> zW5b#>ed3aN^Pz@y((Ff@Gbz}~O^OXan+qUSJZ?izE)l1xCe@S^yUgF>Jkh3a!ys((?}iCHUgbm` zEX#@q3Mh7V!w5cLe*ZKGEg5`QjA7CNCjQj&rnSW3q3*DJV_L@)pF8iv6?gf?c^OGd zww2W!&_*^HCI`$#m-pLxfodW~*b~0=!c|3d6dc$}@dXMwt88?kfyXkq=sg zAWA7bf@nNiyDpVB)Hm#ERQYo zoal~?j}=JBrXl?zu!UbmP$WUoMYZ1rcsh0=T27}bXF06w;ea+y-zsh{J zI>)13ZXWtakG#{LcC!F~K6g!a&Y#4!p3`rbIb%)e)&aGA-KAZXa^dFGk%Zg89Sy~_ zLI!Xc)CSZ$b8)lY*LK+NfDK6Jc?$fTM&&k}>!%;y9Xpx(9ml&*l6?r1sr#G34c!R} z_Yxz@H4o;;!|mwD6;Y7h!Rt)5@dLlHo^nsMnBgSf6SmDzF0sN27+>DH&kU*t*t;7~2JGLCNM@%A+bo(1S_zy#!_-3}V>TGIzRx_Lxr zE!NQ{u-8Wa^LbYXM^m<>#Ff1(UMJxHpXvKj6aKe0aE4z>{(qtP{&YqEPiMBjhX0TG zpnp$R{@GB?*ulZ}zwwlR-8K$g@aiLe$!bEsB$R(Tt$!H&?MIh|f#ol!m8B#Tlfi(% z8=}i7;{gMN^i{)PqhroZP@h5h(~jF9CyGQKL1CyH}`|vI6=Ngd|DM;1OCp%OIV%X-j3J4%Nk2rDFRb zZpcof>-gGZN3ZGx&28(;n8H{-PjwH*I!&4a*{46d<5E;8Ly*p9%^(QeSoB6?_NkMjwxQpIAtGMUs+CMHudK+!`Pc_GXWcMRiWc$Ce4z6pU7fwB{70OHUC zo0mAsbWAfn_T#sA1GzTEh~A=M)wl6}Ha~9CI8a8zrz#T4ISg9*bY@sNE626SJQan! zWPk0cOpdGaMNZe-!Ja3sdS1dK$C4D zhq(V_-u{A9kStmn>=&E@|4rr6e}j{e!M{P%P3>Q3vTi&n!Vl5$U||5H9uRAEP5467 z24ifDbwQbiI*{kt<3R_b@Qcm+`S#%CWz6?wjf(cU4gm&rx)6#GI^T-ilzo*gi*cIK zR6(~njboOhd>xB3L4qaWfYH4E4p;|6h_n7$LBE!LNjyTs=f=4c2{iAjz!}C!ynLGei*S8cWJ!0He9=OKB3S%FK`A@nr+$(FPQS~ zp>rp>=nDGwFC?+LPTt@)*-Ae;h{o96i1lXjnYOJLZjRExjjG_ zn*#nq62#M3A9H;>f#OpMC!!*Q2o_0E3oxhfKn~ipL7azLYWML8eDAYYi?r=@4VE8P ze%h}e?mm-l>dS@I>-oyl2z1fApWP!##nP`Wbt>~Ekna=+|iYBn1Rp+zw>J;rEDTR6zBa!Kk4OrUfVNrKYz4<#In zx2ackBPr)3spb@F_{}D8p1zRO>OB2J^Xgv6MiE;`46Oz7OZ-1dkd8+5D<_89B%QIW(S6eg( zX$n_%FB~nmRY488oh2(9M`K)8h5KuZRiqgE`)3Fo(#k~a&CZpvBV1ve8?tSze?3;? zD=+n|Xi>v`Z+)-j0XLfMdWl(0_7@ABh^y8Vr%WnMt-F2a;twoO@T3AcrTcr28OcIE zJBoczWPdR z(zh{n{*u1^ZCU@l$)70yFB4-MQ!8^vv;VLo5|1tevUX4FD$I9HmLEpjL_+Qlr zHi!>GswEVXbzd(}wJ)*!pNHk2Hea2R&Hi$DLCV^;D_>1xz)C;2;qsPC_0EjtV7OG2 zHHym87allU!(?{iIEGvXroN(j%MbzIx_!{oHTWDy{;|Uh=T5NiQd?JWfm&3wpr*R$ za;}@`lbdQNes7gHrZK1x#zrUI#bTAXdg+pufD!pC-+J72&I)X*d9VnCx zrmT1oy6L|()&OW+qm5TqiSx~Z=TQme-Ws_Lgg5Yn09{kvR}Xk5S5G%r46sXe3#E!l z!5p&G)>);Bg9UmP{zn5OW2Ft_~uX z-RR=4z0AwvnR8M_XQBBrw6KQNJ-M;Z!`|o%i#T_IAM#Lgp8TG`*+Q2>Yp0Q*S7nR} zE1|*bXA_k~z3mjGI&X0%owWywSJd!&tibRK7EE=MibP;;G&K}f*d^7A|CSFDUeY19y|ms zPj_I0?zq4yB#XcigXZu68?OK?4S0G2_93Comw$QwEXvA14tIUbXKdcb1%H9V1y3E% z>(%EEB?k;7y!|-~V2j~yzJ}Q^-Lv606q-ZYfjyu@W!X7Ue%8K>~BiSi_D4#9{y?HuW zLhwd52VrxS-RzPw1g|eVn|IT3U<2pEXYwSiQOXvc7h8oZ$a1JQH`shBf5LwcN5)z; z@F_&u;-?CVT}3?DB4$$SC{)bp);-7oIti-}Q0BfeC3#+B7P`e|#^Qe{O(ppA1pn6w z`CmS|e-a8-wx<7jYX5Y@e-a9R8~(pMg+B=eYg;2@tN%2KKRxk34F1Qa@%J~})R!V; z*;k&J`iq;5``U*8&r`|h{$DxBx!S75ssO@|sW0)+?+0=hTr9iR7-+4esXpIZ4pj&n5e_+$0!WolX=&X z*2DsUgZdOuKsu~pKxZQmA^EX|D6e#@J%KpSH)F2da{UH4ZSX>mjw7!qNA0>$MR;nJ zweRD2I{8gUPEOvzQzG*|{#9K|#F}2DXNvJtPk>}4F|p4ZB8LUYo`HOy0)4{d4{l5G zG~XXmm{odWz);k%t}1!x0}n}BxjANC!HqqN*x|1wSzbpYQSu_;uV0FNGb$BEWJXpV zu|p{huC0j6^+%Gw)xPQlsdRQhnf%75?nRiS3`X_H3YI-})6_SbNe8OBi{8{0_7+2d z!4-9zKh?2qTjh$eBg%}BGnEh1AM+xLSF=u0aMj5z?ykKI1?C^XS{01pDuNJS9E5FQ#r3S7z22H_+w(JuW9PYM|k zaHRKXfCl&Fpz?w}8IP_nHhRJi#*6u>kx`b-B|kdpFZ(p^YN7 zj+|dWLY)Er2tdsIy2Yu;RP!&^utZd7(GO}gXd_SNpZA6Q$tW>|5Ic#B2;+UyNb6z4 z4Mh<^htJfOZTC&Gp{3li`?IH zjej47{VA1nGBbBD(zVlfaB}|-0T|IA?)zV@{>R+Lzn{>b(Y=egvFqQR-@hOK=K}nF zyuOjO`M-Wt1j+wNXg!xcD-!|$An~hQ^v?zOS1SX-zl{Hi*yhzwZP%I+KPv#9@zuCW zTmYq3qE3sOs<*b-jsW}D0aGpkN#)xj8{%aP7alO5H@SO5@Y<4*2geDuyF@HZIGDS( z?SggA=lC|;y=qtNlXrAUl_uEvi#_FIb(fQ?iI{<_AG8?j6w9EVE~7Xqj+NCZbV|0~ zwfiY0#>`|;yOa?}wBwBiEr#b?<<+m?CG%CJdmg-G;Qcq1j4M6H*olw#s)$oP__q}-GP4B+Rjue-dM6D#}r`$`#=Kq?_?rFvfXe& zWH)9XuvW;AJnn<@GInO-A%W_t!NelzAiRf--bJse(#VL`!YZlL4sDvupU;f<6)Eg* z$a;G`|0X7B-*(4aI}6;|!`pYm3ly!{HE2_WzQLkAXDM&WH#2skH%Qj9J*}ghA)vgi z(}}I88NDhx1ZC&xM1yKRL1|a4S7JdzF-sFX)zkf8loSYkj)Xc=X@=d4F4`Xl@`v=2 zGBMIwKgsdHt{*m<$C&yu$#+{v6 zhu89XMn%PA$xxj5xn`+a^7g4CP>duTMZ@h&AVg;GCdic9QKYyp*p?A>c1OlGy8Y<+ zC`x?A1af`})_#1y|Cqf5hz(y;SMq?Oks#eivK^iF*}GY<3Ej<~}M5!wE=dgPYhon?d-5hE+twdvZEl#^D`{vxG*=j53`fZdszN zuLX0{*#1tIOQEQ8HH)~1bD4+TTex=BNie&C6_DCRI|3rD59gV@mha<|XH6RJpUfk` z+D2)cftqp8f%|1ihse0tmiShN7V?G&D@qXVaKd*;KJ@PpV?f$$C{A9i5~GF70eG`D z!CZ$n@vNf$Ef!4u0pqv%NArFBz1Eu7LeuIIogdRv~ghp~Jf zRA#Uc?yPyab`Yd+C?c~AhLoS6MbOuqEfjWuLZT+c`A!m$031M%~!&iuU-KrHq)6D_h&*kiQWlLoA?lMn|#D9(^&w=)^ z^p)8eaB2drkhwD?;D0qK(>EAJ@qr(5*tcpM!K|87cubz6`VACYJ5VC@5VtOSq0I}T z-$dX|tPh+oB-Y*HNu5EmjT9cHQ2eFWpXKZeFp@Tv_s!xO;{~wiy)^Z0N@$n& zLV*XhqEJp2IAHUqA`GI5LnNVWv;fB^AAtyLPC)L#ClWwI6MhdYC@<7%e?ZN67Y5ty zl;5H?OZH(bwwPV(6Q7+BsUX?WGtMs$g%9*p=bcWVmWXQ6Djx^Fwip|`!{_Qvg z3WpzD$>xoNZ)v!F$;SZUX~#_RQa@10Atut%&U{5{pOHg>BsGWE8IYTJ`o;1s(d69y zO1GTF84Cr)nMMl-AAHc$c8Ly@`}_|vUgPsm$k*GoFE zR|-4H2ou1qxMt`}>hxSIa~uPqK!2x0<7D{!IaNhuxN8^RfVNoitrRwiIhFuS!PY{D zgxesy_I`l1FZfN$kgRG{xi2{0lj9CoSd4dWkJm$ib!zWa=p?nq*w;j|&@!D7RRDGV z*H)3Ux}d3MB%?)rR-OikgO-3<%Ck8IhdJ6uftuN39V!9uxoHjToG7I?1g8Vd0o3kj zbpC2d^_=XGUVy7e&%w!0Jz_%So@6Mtp^$XxH~;grYW5o{8{(XKt;MP91B_I}9B$zX z>L}_l=5kPI2eezBLvydgwRy@jLX_YFe<#2enM+T#oO=+#sk6Kl(^?7z@3!KeOm8~o z21_?_9YrhZsKv3<`Fq`x8*9p{?({cIUoquWxN@xALTZP2yt) z*4HuDhAyz`cP+61vq|npwSKMV@~kH?v%Puh(*(x}faQ4}&pS?g+48@WxC=u03Vwl1 zo|;a!wjWQ>pUQgX7?pzWr9Q16uyErrXByjKmyKtsDLwGYjSvlsI#}zZ#b1(S-c{n> zb+Hw1=o?pao1+|`OwhO4cXwh@*TE;ldRmrwT9St%IX=tY-)m)<%5hse9zS7)f;FkI ztiW7bN3my3^)8&c5+AryX1oPQ9fzG)f5KZ`Qq3ZQ-$i^NqYvTYFmxb1jfWC2kVijlyiK+C6d`7uI8krA(@ClGxA>Gt6=vd> z+~Zdljx*)Z4zNaP%6N+Mhet}E9lv*{MNzQKuWGxCLy7cTQW^Vf^=Fp z@W2AHPM*W+%TrxwX8rgPCTdm!8Zzg)Ka}fwHJ)oMd86R4nHaY9*kMNcoY6&9d+4xS z-rvB36{{_(y5MPy_K+fZqOOgs5h{CCtEym z*exbHpNn3%y8pZoq@*|zDwM{N^Z!a52h9Nh{>*9r9@`j*{X>O+&THwo%GQ`OpY{fx zc&_5Yjzr5XtDtGXZa>4O*d&4L>dKWR3r0i;$tqeya5T6+?$dP$;N_cWCecV@db!3! zf)sN*(8EapanJ8_|FHMg04r_%} z7vjol_Z%vKW{R_7v3uDZNJwSyAsUJ$I}@hr&006SsT4L;nPq!!5s77UzLVi znN(=Lw7PJmBqh2x4Vo@T>EUoHPP;5H+(`YVy(C~mh+!gq(dRc>n}pbc_xfJEO)9_@ zsy-EIqMK?|8c(eQ-^J@l(Byy9XMp>%M*DDl9^b{1AoKl@788nRug-DFP9TYz-p{3w z0Y+*>Y;DDrU3)l-6=e3-LXvdnJcy=(NN_ zyYe=b?-utlgIURHP2-65Yq>u;Lqt6)(Ir^%x#Rk;%?& zgq{KRmUu&ez~)E`GJ5DH#$baSwH1F$2jw`xjd#vk#PkrAPVOvN0mG%(pUP#1Qp8&t zkELeLkHThRm)$@PA%45Wpy4bx;DN*RhZV*mub=}oTcbRoYW~j580Bz;193{Ar38{_ zTV%b-%A*2p-ct*LzGZaq8MNE6u(E}oe>r1;F4fI8SQvND@@pl*VQ3K>4Od9kjloV# z$+`PxR*2dU#h#!lzc@NQCleSJ$P=fV17*7++R-dc$5N8cF0BR4L-EsqMidKls4iAq zH&U#?5P`Ki6u&(;ng8)uh_#m7zqN@IGW z(ImDtynS=q;;fD=S&M~f1JHX{IVxSIWj8})$q(}LGzTca5Pyg@N7Ox%-|V(;U+>u}%PBddSdIy>brek`Vcp zK4o9zSU$gYJas*hN?*)y0(=gceD*kZ?Hxt91v|ujQLa?CD&x{wY7u1-k*ZkkoS6~9 zNO(XTG!Mth?E%Jk1OYUJC%84>x|rp+Zu-0Ms4y0KQf;>I@Ew4l&(ML?2*V3*+qimz z>|vs36!}S<&^&b@mW&Y>O_9O0+1N;OA5;-x3z=dcaZaWo)f@r@j`$kMK3conk zT6hpam>Edj9pXdSN7x{rERvuUM1qv%H`1^go*VI7Dsv7ghQBGN8#;|2qE)mWvS__a zsx%^LC_QF;hOen2azz@{FhY+m<>|w^Tk^8PJF}oE4QGuOSnQjRU7?VYT!X$ZTT*z8R#VgB_y@1O zIv#SX2i@uKyL}x8gm&n#lokd_zewPpiYUPVzhd90$Tin6!gR)Ijf+bl$4=~C@a@sS zAV(chC?Ji3yslTUondC|6N*Ex$_&Guh z+aT86Df<%A!A1Hx>WMO8u3TceIWY7qZkq=1mk+(RQ4QHQOC}##ftWZCb1uDR1a((H zCytWB`Sonqhd~g2!{oRuYzE0NZ3%qOrAP~SoiOu82~VcDTW8wBUhd3Dl-sLwwvp+zMVtIF@Xa0hxSb|Q zVuZRH9odP#sa`K`=z61f>`bnrKWTNEUW6m=F(mG}4_y$z++0ZO#)gPUjHvckn^oe> zOz=B!fZGGD5ynGb;`*lkl%C!9-rO`Q{hWFRm(WnUC0LVPGaKn51lH@lLnkhy8*!I< zU_|Lc7j&5Nwj2JCfs}Z$kG}UWMc*J=ZLyc5|I%hVi4AK951S`A;O@FmUJ-2N4#zG$ z;)ab#l{Zd?KX}sFBnq?04UMWsmAB@_{Z)zjHtiUD+t5BPqoAzU0_lI#1L$LJ zw85iR*bDHiwz;&s18;j5cj-iMD#M#FPA-lO-F^}m`;>Wj!Vipmw5l)rFsNi#WF&!S zka(QpQFVZ0Q*%{mqGJnLdxqC!&_b+vbMkBE=N$0wu6ksK-~sf?V+|sR*KNVF*`@ay zS5T1NM#Mi6G_>aG>Wu4gYr!tlpA`E`ZEgy~Kaw43QD6x*RE!GLaU(r+r>}12pFHrZ zub)>dyC)H9)2y?7$*U-`&v{a6h^j{|=>asg zw$)voqPpHjRTr<7ifEjBJpNh9$rdcfCbZ{g4pcx#2dw?l>MBq~5=Mc2wE8ZAXQL@? zi-i-#&sUh@1rwQbCEl7+R34s91fNNM#1A%>csu74#cewuMVyPx6k(x-{@nzb>nF%D zb1t{jas1GvZaD6W&H-m1FiqD(dQ(Ahe@hdYlJWWlo}?t$d+`LAZ@dQUAx1EddZ!&L zwxsyC5I6fG*WYYeQptldjjfXR?YS%kgq}GZfF9vJRW2{WSj?S zTsfF8wT>2Ahb7C2Qc2>OBM+nqBZE+2AWMvV%NoWe;Iy1Iw@HIuY@*#SYV_+d z2uWqvsDf=D$UFoQ%}dTPG@Gf`o8v`?&Mk=p*IL=~cTUnbmtCX5@#jIK;#;HQYjxGX zx9LBfXnEfgfFx0S(UZatFeqjz)N%|C^Zosl9#6FN@@G{xdaj<~rBXJ8~BNQCkXa z`o~ul-)rVJA`JMRAqu*tf`A{?og9XeOp!|+Zx)VNZWN{XY6|?j!g@*YO~l8*QZqj( zmpHwwpzBfV?8E6XyAK=fQgjX?!EkhAnKxygG9DRda$b4VDIaSm6x7&&Ti**|dPR2y zF)J6^kzupPiofw+GZ+b|NvKXZO*?FJM+UNV^_J`{*JS!2_5W1LgQub^=OQu!Hq(8Q z>|!0b&fP0gXC%W! z#XgiaZBeUPQfx#L0|W{(AmOhlDxs>^delEvp}a7u!;yw5^?Xdw!ii>^WK?g-_?nO^ zaf4jqTsJJ(_$g3e^=Z>PhGd;L6Q(s$+mL)^>7ixLyGC^PishDhrGP@*o+0Y+%HrBq zb6TIp&vP`c=xF26GS(FyEK$MFCej}{k&)kmIv`ideTS{7ob~22znIvMV#W-BT7J$N+GLg-CN5)IQY2@NqLxZV+{RurQe@T^iQa~w@P`X0Dp0gVUiSve9EllJk%IDe}L+_7*M3is{oJ3MyM54PEx zI*-=yij$DgN*R>~nb-yUq31YdiIZ0txpvX~hEP5;5>DS2_Za(BG7(*EnP!9KuwZ(B zUoY_Pg!}|jtG<(1b1W*nkQFgSlPi6hc;3nZV)}@Xd15TGGYm@txUhk#VI1#!Ke<8f zwwB-0m^;pEk!$JHHK>WhQn#G_fd|RJLUIpRm)GCFVR(sqoNruHISRo#kj+agwAfXb z%+W_K$`S%r30>&=&Jg&;ed}@|-^^QcT}eh-X#rp$9|-J;HZQUU{YKj4^Cc`r#O!IgFA|JK>MR_N!Sk@ULo0xnC01!@bS5=yQ%Auf(DrqQ~csZe8{}iUx0%fs-2;>(GuQA z^B+2w-F&x|muOimcUUu3c)hq?4iLr*P$!>-DRVf$mDDB^F*+|WXZ*;IlU)jAwg=g? zKU8D)OIKKo6s#d!yrnOKyE6*v65JH?8O2%&x1NW8VgtnhC+#rqIzLrM5faqxjTGb&~eOauRveE1;V|Sed`vATCqBcZbYB-5%64Wj0)I;z=_TmjuHMvj`OY{?oI)tuHy|X zhjzQ~=u>2o$3vCoD_^vUI-%xTnFj_f95f!2s1O2L_wp@ARYj@xU zK<$U3{jQ4Q3TxTMCCgz2hf>AK9DpL-YUEyPOPLOqz~C2T1;q5`Ti*;}Q@7u=j_m#Q z%~x6M*6Cf%9Pd-OIrqn{VKDBoK%+{!?buAE{;^axZnO+vCICX~j~(f79~0yD3H?v% zZpraM$ON-}CibiQd5dAV zf|t2RU7_?q$HaZH40GjWrwIWP5~3oBly9B3+{f$rj-Y>{*{J>cgAElo6XY2k+N(}% z8mU79T{eFPY2?6@szX{`|EgOr^G$ZuGR+(@LxX;NyvPWV9>1y=_v7TPbe%L9Iy>mC zMB(K@r_mylNUJG{q#0#urm6#~*M33`S;91I#;fK;Rd{IWfa7VR929DtAKnY|g^g@4wr`MvkCdf&p4m)GnDUl%!72-am5WclaV&rj zKOH|a$HY#fO3iLjZO6xH7Vf(1p$Yze;)+weK_VPypk3rCH)lbX!qTo9Z6Dbo7@2L) zj4znC2ujFC*Q(toP4QJ8AjpazXh-T6h=S1q&v;AG0T8rhpZfh?95 zGeN?>@+0Y#6gOHf^cgow7x$9p6LSgH7G4xgiS~nv7m3G2N@L>$S5`ttf&_5LRBW$g zXqdX$7J6H`VEGtiKF)y<*qCsZW-@iUM%%YAb80m;f~bgn);L`}#Z*IAyjr)5FTl9R z3ibeMjl6k=t!8ZY3C5Z>R6Q{Th4;HKVS7WO;^0KFT_vq4JoqfhX5CF6CN^Yp-M2c7 zB}*%F4=26>{88d`CHfY&jm6FG!JVkVT`ajep*5^vLWMok&^AdyTgVv0WOcxwR-`|p z@hm92EZ$6#Qm~B*iRGE8Nwh2NUIM#|P-wrA@}MK2n%-B#mP|Um&NX>oJ3IlHxLG&o==axvU6Y?* zP(v4*qK)u8uv}ed#`pHy>|O%hWUwO*0qqAQq!0EUYa;&k_#Fo)Muo+MA0U%nKtyOR*v*7eIl#MLu1v%I1r&u-R%aIO3+)At|&J+qV270<^> zb8_}GpA6V8tQc(oo~vDU%4uGaee0+fZErv2(?%3RpNroUC*~ zPF~2j@5s9QA?bOD@87CJni?Gf%os@nHZc6LVMvjgym&ckIr77a$Z|2tv@MAj2K!_e zWoHXGCQn&^OrDaM-~%FM)5C% zF*s`F$#+Bm@cXrVYbj>=sWFAaZZ%&g#^c{lwm{s__js!Tzc%b8>X+Dy9Y9drB2JWt z>nI3cur%4V0_cbM6DOXG`Jl}+>I%SB846W}luy1wK7X>>K8qS?HDUqAiQSg2d?w$K zg0dv^6n8**mQ!J+)kbV(5`K`JnH~k^lglNc4m5c>#z)sveJf(6xIla%F8_Xp zeB)&SmgpBDGA$5j9zzJU!%Z+~z-@FbDm4N;2PPaNCt>iBIMdOU8}nf$nIjs9kzv*C5z&8dqnR71L1E5es(kKm?8_oAQ#$J&k z(e3PetZ@ExepB_ML0(BG6yR7(m&2^vCacUNh!I+F8G21+3F@UVs4Op=f3>52@!R&= z0Y$z;V*Zx9%^l5cIhhZpefli~@H)_7_vehS1^gg{DME!X=T7w~K4?h4x)dtOWPYM} ziic!MHupnOw4WJORNN2XSnD(oHnsBKHKu^9i}gatWW#b((P7><3U>)9`62CFr;)`j zfFOMW9qQEi#Uk7lMc{=9(C6@AmcI_DA@WL{j*e!{bhA|F!+=+usD4uIHpp)40DV8j z7=(BJRhPjIR%RhES>I?3(~npDh%sVxhTT#t^wh@SNmar%QYO_&B#dnS*r$r(4m$tf z#g_^*RQr2M#{W_1#y^hpSX|84uQZXD)K*uQ8wO6vQuZy5i2VkfP5)O}n_nlUS|Pko1`i$PS>M*->Cg*&7{$b1uCa9a>V)y9~Q;E}7h9S`Xd+|aN@p>z=#+lWa zE!^<=S?5cWY^-b20F-JLkLzfM=i3u^b7hwLwEel1qSe^ArFKSheM?KO)F$m2gPvq7 zO7gv@gC8gTN#d8A32|4-)PL&`I{^u^!Rihu20l7Sao$?4Yc4J|XDgK}&)ulEZ}&JA z;ADsig*b8PQbB}Ti$^^3hMWvV49&L`l`j|K2MhO2=TyvkHPl@XuoZvM!QUzyH9_rW z7Ay*Th5L~Y1D3*&l_hInvRuatpcyNnYVq`)Hlh@EMOQcmZ>MLCCUF?>h-S5pg}y?_ z2S}rW2f-Csn_6UQl*_Q47LymjRo$U6yrc#?M^#9ORw4M15_}$$3acX|&?f0@<|Ng~ z)gFUVn=_;;w;@r6etoCO3V!Q*yBlYACfKfO&*-Aj&Hmkf`SJ0lUpDE%5v`6FyuoqC zD|$!%p1-kW`kmifO_(F|p}Px8JhqYC5Gnz_39u|RgloD*ZJv2qm0RP;G~6^EA=Z0H zeL2@vqZ`93tHLc$M&Qe+6@!^rfzcBX?P~y|wGgPg{MOL*x%V79ud=Pw%PXHGpR9Fm z3M3kW4u%Rix4|knO=22844e!eF9ruway$BV9G6pB1yJh99>qBE{NmUpr+%O5J^o3# z9sDMb*p}cRmjxJi@yfhF_?|G+AY1Y&Dq1 zR&S3oyouJ1^MRJG96qjM+=AsQ+!x_AjZb+)=Mnt9uk6uw`G%z{O0^Ge9B9;Q6mPhh z0qq_VIz_1sNcm$9$!}lKR72up2X|e-Ta_Kn@UR`aTNHWc3I{<~(?KWr8uEzFKq9+L z1JeBE!1%it+U!=kqd^ng?S&Eieng<>{AB z7O*Wt`#yCWU}5sss=r4m#{rt3>HdSseRI--*8tx1a`$zR=Y5_Q*j$6r(CYN2G=5XZ zcJsPdIeWBM7!~B^-Os{amf1||A+Q*YQ=XPx>w>3-UJ?$Jw-1=7;&jH$mY@$~esT5O z>3iT?I;|2lJYQ#!L;M4`huvXdQCb2?SQHX?KKrB|q{cLU-F8cPwY%EnEy|Cmq;5rL zHZ!!=pFQQ17v?Wm;3QZy4EyKSSPy`!eU1!31BIKdq?kA*Y2;SqnPzhyYg$b(f>X2d zsgH*=xS9tpy3(3=4HOp!CxChCrC`(O+3xc&Tj{C+fODQp+#};srugfw6KA6oG4Agz zAuQjXAxl=+0kVC6jfBeysPbN}{+tpz;UsG zsYGrB6q=XCpRcQ+Pk;)Aq|5P{p0m=HetibDx@t7Z1WTU}^C9)4n|z&QhOCflwjT?F zx=2%YPA4@}e%yg~gOM+-Ap4MtiEf5ehQ+d3BCxBInH943s0@$fgyefPVM(bB%a^Gc zE~l}wOQp>FXIw}MoPEf7284QT2c1|sFIFSG3k&Emknk-#EM|jvuuJBypWUTB`}Io+ zJPKNYXsuk|(o1S%QFBrL4{z@jEJ_%p*>2mmakg#Swr$(CZQHhO^K9F;aZgWo%ydl5 z%;SBi_ll^f%KS6ex9V!sH7lD5sY;{YaM9Lm1{hB_p}}}asqEK?ITqq^G!VvonwOk$ zZJUdbuagDlTwMaorJJ3$_GN#PFcGvYR)E)3+F+~()t*>%yAv^sOm&yY5)H5^ za{J6xgOm_>e{Q_5iAs>@;*%SvB_%vJ=`iT*#JJa%;2)5{;bExun}PabbkhWwavd*g zMbAghC(L%#Z<~htYc=RCJ8=`dgJA-E#dKygC%W_w?t!}qSf4x`9ZrY|7D#y##91~^ zC4e@;$0-uzqqHy@`TYknu=S{@q0s>;=!gSSWL);@6LSg>Tku)ISxKu3QMKx~TD;UQ zIYd&Fr^t4{?fFkJWx~~?{}^H11cd>c0)cmH*Q5LCeGwr{POBEsI+w+{>)_T1T0!4u zIZ)El+If6LdLUplCJgR~u{baiqz;MX*{44MX@m$RX%69!?AXPAD%eO``{S`5WKz>Noqp1HtU#c;+5ot^ylmb=05jp>L6MH0`vi#S`%W(iJnJSd zSwR@Dp&Pu$sNe4_6u>q2sX_7|GdsRSq74^syrTX0S))SZ!53NUweJ9^OM)=waGUuo zB(Avf8+;E3C=6bbuA|WG+}uQ5V@tC-f+&QutFG`6bB}ogZnVE$UgRks1!sb|Dv~#x zrO^MHtJpuiaB+IV{6EPq)a}ba9d#1TAMZ`6ni&0-X7Ci@=gIFZPsbs$;N5rXZ>b1w z&E0uY7f$zGu5*s|C%^Zf$zYINE+-R=7|a%aSH*+7_oLHYhCj2}sSkrFUm&jowK<}) z*qR|hAF3q{3IhJufuTG7*KaO&3X1S`>`zFfNGF@=D=f-QT381p@_)?<>@1k$nX5}2 z*gLYQk8n2%vJouVaJb>V#(+E2YB!I49mttxp2XDtnait9pzNg3#E7Ebn>~J72E+5{ zc60C(+^5O+kb+6<^zhsA64)c?4+KuF0Mz^E`PK)(ntyOZ)${XV-}mFZPiQ^HzrSNk zSw+pl5jPQ?S!y_if^OZOaEJJu;W;xei}$m8=K%xcP;JH*U@#tvA%MoV6qIA>$EQl& zj}Xtjpwd5l!<8SL+TY%oeyUg*!CF~A zQ+RKw|MM&X21FhjS$v(_k#`d;@u0KZHUpAD%dmAx3yu9_P{>e59&^B? z-Ui~B`9W9jTC!8s61S7r_ zvcZQQP!s{@--oo+K3$;yD}Wp`5gS@N%3wxVJQTOT)3v=8!8HL*BxLXS@MPoGSuH;y~4>EVf#qQ zMeiMBb034<1+E5@`}zeI*bY|Jjkep_zYJC5Gxnj0ms1jLdmT5uy4K14&aDaIVm&GyI<>)QHKWR8u#zKLS#aq&N?xg1y}%>nn%Ohvr!0MKJx!WgCNG(phF4S5xa!$F>iHGw7XL;0cp{Xd2gO6J6M8P-{#%~wpfE1-JRj!;CWpg#k2+>qv?Mn zlXi|Ty+$g@E+uCn2rPSK7a-MGWJvoavNY#OYLJ`;Jl> zwfWlQ9wo#?Sfk?=CllhyZqxUr6rACmw>x%<-6)W6D-G>Y`}OGjngFab(O=Jb3I7_6 z2DUGhp4QOioKAy{2n}ak>pjzv!ZbkkK&rDZuD6(+7FPFlF*$adipJtcCfp2Ua-8E? zN2kQv?6tni|6qX+F9l(b)nG%sGJQX5PIq|HM|rfGispXvF?>6%@VL{fdS05Ayy{nT zYp_wlvr0JsK7+qo-TFFz1BtcynXi|9|iv`>_rueJj`- zSw$Are@Gsy65HL1zk=)k%sjg`Ynt^{YE;nq_`vgQW#vm1m; zH9jOtbsaoczm**yEpk<+A2EmHveB{D&9O-;C#ZjfXI%^-mWn+b03)gtXYN4k2PHqr zF)>J4y2hZOotMZ3g2zVrwIy(7rZ(}eqm?jGiVZqQrD+kLx_3ycQcyCyM|WPSVm56~ zk8FDnMNtfisU78EaX%tC5bwYwWptsP22k!S7&l@aa($ce&M>tB)PjGOQGyzoY@k0y zugq8!RL^#5^YA$P%!wm=>3|1~VH@7PSsB!O)f2*XfothEpcpaFGFagl%fVMCSKYuJ zJLe57Z&X+0RDrX$WQUnyAKb314eo}DBAJ%;qQQA(9n`z&!9i-E$H}pd9IDZmo$u9X z@gYbB;IgXojQtnrVf5cY4^;mTxqqMsi{bTvAI^9@gm?yqq4hmx` z;#F$Qzsd6m_n+0}R#h#^P3PW3@5tNX?1*`8O+5sqIiv9->pq*}cdM*nalnLH%_mkY zZR|v77vx`rgE$fHZ z4Yk4;mo+XY)#T+8gn<(h7mC1qN{W`mVif(g_~KUMD7ten83r-kaW{Uogj;`K($Mnn zPf=rIdUPP9^XEpQ#XD@IMb5UZ;@i8{)OE+8^LbR=(kk1gimWm$)^|k3rwFaDCksl> zr6^`)*AE(R?fG;=lB1VmRKhm08f9hKQQfbj_PetB;mSr>ctOc01av@b;19RdJaFf1i}#fN-3@U#to(CpS^Sm+Kg> z^MSsLgZ~JTOyoN$Moj3j6+W$tFO8k|Ip%JpgGq;_!6B>>_|+^8<$Ws+Wg7{S?I6S5 zhjhoWk-p7~P2Xx4r=e#iny+ou-&Je}BlV3DZs)D)X2>Y@fabxB-dJu7vNty^!-iaW zox=%;zp+_pts(;nB^Z?Bb|`Jprz0gQP0C*eW1Q{EKk0bbZC|px&yKrIK+&&Pnflxy z#Kd&AV&FVfz3uu?a{7P1Fj@K<`N&=fLvjGn-}X)>+B3gbfcK%`U7k-IBgl;z=pF+Q}iY6*V!{$^s}>* zlcIt@r3#!4rvcy*=_I%PilbRLyFK7odp%t-_EOCq8)J?fc^jI8B^QJ>&-PLCw_Lh~ z>F9+R7geJRKrJSI3wv+2c?ouEvMz=%U}4*wP2rbLV@}N_1mb#d${7>kE{gh9%GIzfeHn4hajN0X zRbd9S=+?-M+$>{M@=5p&9sg#sT5s{-9gK+(aoTQ{5jHDYR13=opU3a1AbDf@kWHr_ zS=h7QhijZ+kB|&uPHFHkY`cUL)P@P5|2@JBW@PRvSqw7l}~sBt`$ zK2AWU?=WQ@yp2tiP0?ze8h!_*hrWeMru)|Vjz8wAHtZ57vy)6}3bucC45`-9X@3~g zG@S^Eo`7z20`mWOPJI*bBs@BoE%>_HBYgk`xoo#4`LY>bo)pPx=vYghD3SPKDjuf6 z*H#QONiqJ~ZaLfPyH9*=Ka|!zARa>qI-h&O^q)H%*X`e6SqtWwY?fvGEGmWE0jq?8 zpU4+Lu^`0A7=$k2+ek`yNZcO-UbJpjX=x5sEMl!_!*1l>5Z5h5aeUsL{m4U%6vuEl z_Pq)-a}lnuSM&tk6!?rf^d+$^o>BGOSaDf;l`O3){VD$yEL-*l5mwu}^pY6?mpAV( zuKXSz|8_9bV_rk>d{jwd&$NN)Yj}qxoSQw|Meuw=L6O_-x>nLWrn@jV3QM5mTjKdYMG0B9zk)*`4iQiPvdI1a!aD!wn{xf1+y0*a zmO?IVRG4sEwe+#bbk!5s>)L~B=bgt8>BDVDavMpfIv2LIVY~a?!Q_2X_d5It+~Ryu zJerOh@=(%1@g!HH)1!u(b^KTrld<5TO!h7XVF9kxh^rUsHDGs9xd42Eop5QG@z^u& zZiqK4kSqvIhMdAMk%pdR;qIU0l)_TDT1W{lAEsQrBC>*mB(9(DnFs^lK-tfQiN9=c*ts{G45P=T9ZF zp>w@;^gV?R*nbo%m9d2)==3JcF5qvQfTC>;%@cGRz9`dVN;L^rq^I6=<+-VBlR>UQ zT4f4Go;4GS7DUjoe`!^aP&J{z1v@2DCGQ`LSt9GY;unVmur{aQ?;Ex$j7nW+YkDSK zu9ZG0;`8sLeVsY7Y3P!Xt|n?>h2qz9owQ!Q)m% zHjKwTR^FJT`?i*=tH4RT;Q6rocy+bp4fPcp0ENHLWJo1xS5}Qliq2e3kL*sj2h*6% zf(`B|*bsR~18;q;F)z8Elw+<6Y!O7WvhXd>@k;-kDSK<~V>n1t;l|^MH$9tz_Ji~z z&d8;Yg{vb+2|gWh$Ff2@!|vHVCDVqr*&B|1*;3ddnT>>G$m3HBob!ZpjHe%CPvB2(citlW z+qJ7oti=%Y-2qdNV2J&B5SzhL+3#jP7>_SKEH(jQ4UuqCAd@lA$>RL-J{y zLPR5ul0qe9;1l*8C14SaVirdxHh`H%_N z5(mK(k;I;kP7~Ore>bp*c`A@S+ze4Mh>ktZBM+T}ddntIa4d?t8@<;-19}By<*A8l zC4T5N)5I1^vjOYx_{;QcD1ki+9>asCx?ubG2%d0n^j3D&*McRXs}`}-Q}DES8s`aHQq7uh zfAP&75xuIGXgYa%E(;10ErZc&iNA-8->E|6n4pI0{uX3JyAVenG2G|4t)IhmT!irH z^*(Vuu8OhajTuO5$`Ka{7I_VXBGrpUwwgwl(07gu))m_AfsB@E^8FzbcGI8zlr@Lw z&w)e@K=v3R<$e%scI($!GVIhxKLVX{`k~O%z4HMhP;eMnR(>zMEFesf*O$*999;vr zHuy3J=L1-8)`A}Shi*_DZs068YdiNkm<-o*71x zh#M0!iZIQ71aB5wbvZJB6jI(*Q1eDR5iX`x{QSvd4J8I^Sqp!nA(C*&TcsbVn*aRu zy_K3sjvR{h^fzeDS>whi;`jLZ5^u5E;3rjo>MGEpF^cNy4J_7775c~! zh1~X7(2zJm=tp_DlapId!fGK4wZp8!6u-~s_xUcyz1w$}IGn-@KBC)xJ{7k95@jbS zF{GlCB6-E9w5I5{R4h8Qo%l2RVrZ2qwl%wxB(9v)%j7t2qTa{@TKGL!I=~+7w-v6H zs|0je#|7_UQ?{TKZ846Vp08?5td#&i5kK!j){3wmHt$r+B3Uyve1inE!klcp+PYngP}MP`6iyoPPrZ{LKcsHIs3@)X%(nb2M6mUeELHm zo1%*9I*m1eG_k5JnOk?;-RT(s%ouXq?^sCxp4mS3y$%48V~QSVYNc@U<%&s$zOR%~ zu}RE6pJ}RP(qfv%)p%MF8|+jmL_?!U5nBnhH%`a}8rd^mL*oZMjea@V!lQMyj3;c@ zvfl3gy^g@`u_3ZCNgNe-$6>kn`zJi-z5HK1`d%J7Hr^m&+o{N(_VX(|txa}Z%pH8# z+D7)v_PfI=MnhU>JpOzU4$S(Gty*O)<J9=+tFCC{kauNI+h7S zpnf_}!^i9MRK?PBeXOUjY{V{jS&aRpee3|ZavE2K$PK%XA4E^>=nOLsXQ~Hqh#Kmt z&TRt3=*CqmBOULcSo}3mbu5|an}1FMXXF$qE634FT;OXJysNzX-y`62K6TB0uIYxE zmz3enMI&q%s%<>D=Uvl%fO!towb8lHAf{SBP`}}JKiC{zkD6?rJZmqQnB5s;1SS;h zaGhLl5-!T698t3=6KBMLa~t5zVDK`{ zRrAnczkN%;?AA{{;PzKBGwA$Agr895yw|><=8qdsRC`#b-u_u1R!Q&ptt-F(O|EGV z@F{pYIq#$RPb;PT50fPLKO&O<*)9Fgh_kAW-6kuFk88jWxF9UTr+~u2;C1RGR49xW z25UZlU=NrYi49_bL}0Nsh|sSWoycUW5gSvZs~i(S*3mcb>%(|Skt&8>kB<|pX=W=` z?bp$uqrTjsNL4wyW(@h!ZJV8FQPcf9*W5o(ng?%({@y;G<-}N$++6XJ(0$sS4jRRV zc`!EFYOtieZLUpw@_Q*_u30)Hp-@Jk3oL7P99*1J0ZN=;bD*xemOOQpzL1kW<78pU}4T(Bl@mw=fiXR`2>in^^nPW1CIxI40O=T z+e|$4$CfiCtUg{h^YCrtYc>6QM))51Pw3qmA*WT7Uk`TNs+< z?$lq&Q-4+%xUC0toLfQ4EPCi#Rj1b_H>gfPj5n+}!5p~&PM45x+p%itdDcbrc5DNp z=t_}?#y$Bnjr=g67ic$0gr!2!&r5b3VCN5r<`>oNAE!)9D|j#c$nP{B8oRc6V#+y~}FLGaxq znW+#pC6ITP37FmgN6-?=;N|2r2*on{JZyFHo&*H`9L36da>!K$XF{z$-}|T9kK+6r z6RS1BTYySA;x@D}?{fZv9^Om(7pP6-r-Ha>00DIAKx-<};C9XGCL~pF%mm>)7{W0b1ogr^_eC5jXW9j*7 z==DSnWa_dk3F1jl(cJj~Ubu6vi1rKhJx|1sAj*;K%gt;-iJke!utM*@seYmPq=d3h zJfCv^IWOD)9cak@AMc}*iM6$bt(l#R^M9=Rd(>>~wpfvVy1~Bi)kpkYFU?KJ)%NP` zMCP0OQPYY;obm$q_#?CyCYAX;0tVz4>0G zkwLgb(#dzGR8FvrR94sEugj;DrFo&{jp24uNmV`rJriK*%*dm>rXqHZK&=DQd@m07 zUP1vj!dqxJIjX;3|BbEO?jDg`%Cp<)abYcj%NJ7W$_O}FLF!eVy~$Qm$iPCQ{TB*j zYtNI;Cf3m@mGHDk;j53sR}8?;_6=@1Ef>4v;61andFFdTO3SaUEN>kP-b>SzQyO%h zx~KKYMbl2rTf{4s0qS=xkV|}mSTJA*yFb&(MTx6}8V~yAB?;U2Hz(=2=EWHstCJZj zJD2GT_UA}5hnNo42QcpG#S2I{1?JVV<=|H1$zA71cB-64d0U5kKscW`eQfHnn`GgE zd1e1PssT}qg8DX=A!|AgC>h_m`{DTWrgnKUN7o=IE&y1$3AmXvV)yu{RO_Hz{|Z0B zx~A5g(AGeZ?Y#0^*Y;Iqflu+%m*2iksI`_@?fu0%!LY67k^KBgTiTd2JxaX)Q*{cva0H_8>Sk(U6^Q8^LGOGDf6n};95vgy*!5Pyy?gR5LL;za}4SXJsZKqI@tCbT-c6_X^PP)0XRIKfcr(C z*aDHwo$FKvDZQV;5 zrYU#zyN9LyE#NSC&>;^ozqdOvHVfq-;WT6*v2C)oNUyb8+M}<6l!7TEE} z%Dc+x#!q zXaVnhNMPA7pR5{aF+Tq?;e~~k`ll?%%kw*lEKP23=uJIX^cp_9t2W8_eyvENvyHjB z>aKt-2&-p;Qk$lu%YD1ib*~^WDvO~@9-__FB`xVTh8>!LDgGaj*M*1b)5yuw+f@TD zui5|Pt92MYtv0Ns7G4`aaEPe z0xd=VY#0h6gQTVtJo)Ar|AkasL^BzrPg4o3H)KC-2f$NQyz;dAZIu#$DTN3@!CDDm zv2oq;r%Hr2KCL)bFneIP`F1~(CX_S%JLvnn7)0B#%zPgMEX`KU#t3HkPr(bCUaJQu zv_D{{i`clkbCEXm!>X|!Km}Akr$K}IDFk)c-FeV13nolgU-}!O0c*-5o{RmLo{;Sa zj=a2}G}XT_WrG_DA!`={4*mJ(YY&z2P$|Ls=h<_fc1v@OxgMj{+^yhB-37u26J9z7ChW9;+xb^vU9MR^4r+I8SD+|SZ64+A z4R3N(z&VhYXzy@G&jq#ESlL-fODHR_QsKO7aeU0!?)dr;TW`rxIQo-5jYU+a??i1U8kK6?Of?Y;Ch_X9nF?%&t-y6eDG7G=ne-|0t#(XaMCNeampyE5?1Z?*v1_j>V zX;Txdum1<=e+>;o9lr&Kfy*la{{0d`@89oj3IAUe&e_1!^goJQ&40C=s{dNfSXcz? zkV06WDpJsq59Vf(2GhBb6mczK3PpkncHQ{jUMWSzh9WQrxKDeCCjqur& zIz1hl^xDr4o;Cr|sy35)T-Ci8b=lc6P0&Uup&YKWp7U$QeR!}!o z^uD|txw0XO+_Z)0(NQUYBjy=V4ubl@igS46ObUr|>F5uzByApGfSf{C?XUEiy>bsE zN}k}O{N9O5Wo+0J&>NOuiHW0kE&{vFU32$7N2e&~p2LiWOYI9+;r8TSS(*(B3D3CA zsLToUH|m&)DfgH=Idt@j#3OJR$d*d;yB6+kxXXuLC9sENwC^=gSl{XOIl;K3fv8V= z_7XQ()sOTqejQ9pYke$z;ZNx19=RPSf8hjcp0A3B-GVyDmj*`RWc{o-I7ucTmumJa zZNU!V3*KMu9<4dma%beSyCj>oBMuK~tG{4Qz&DzBa?Q$q18L&9YFX!Ds&c7_3GSaj zYZO#M17A>eo@Xss=&-+vTR|y?!UHz!50g%l!byJ_m@RWf#sHec4B3s4lufd=t&$r$ zHMHNm5$lgCAB&ESnA>^SJqWaCohdTQNKIi>&3UifS8MSby&`HB9>#A1^>g6SNHtd! zm-(PLm3A)8%ysGLVr?+Mn#rA|O9L}4A;x&Mm}2gK-|Z~0l!;};R_<%u|KJV;GY2{> ztBq0!P@~xX$j?8)OM188=>rw-$ODP;Qx*uq?p1HdnCE>h*GJ1o8_|Eq@GGpkA`+Aj zcojAuR1x3DaQlS8?Ehl=v|Y~g^-338RnU|v5F&P>B9Bub9S?DjLTq8T(QG*h?k|OK#U-Y8i4up&YPpf& z@b($e3r?3U9k!;Yr9)^I5(y@D&o$lgvQN*0IdSRl7s~703K}yAegV?KNXyP((*z}Z z@k@G_d{`llEiix?bra+ou~6QOOedb2$AlBNH00g+onl zWhw*>+P;Imc?EeS-=B6nz5@UI-*yg${~F{eHa_(8e+}|6*8fd4`kx0@RXb}J8MR(Rzu<>b%Xo4apT=0jf>A~!@j)Ao%PqkI1;cH;QT5tta);>qIJ2J+ zUDL-NVw$+eCe0RXE2Ak07he@gDo~Qs7@Mo&VV>qA_#I)b_i%k)SO-S~rPN@OKi7bXJoa9VQEc8LYWDkOy({H5*6!5*)GX}Kf+cwZ{W z!S}^WhVcZ>1?HsN>lo#Gid}7w>&{nFlo|*ko71w%J|&5w<9J(P;EKXxdx@f#P^DjR zaIy&_FTib)BpcgyC+HQ$?G~*u%LZhN`R)nnc!x%=8uPin9caW$74SD6H0#(?$`k>C zO9;@}Aj0+Y#MEg1j;=EGlMYe#O_oP%gM03gcu!`IIr+et*PJ=8!$b;o-Ccat;?XeN z-kV~Pv(!BmyNFnP_B{V>{#*_A((oNY-5Ifj^_#iKS27tOC{;pXpf)+1 zfiU`^E{JsJ7cfsq-9Lwb?%7e-d#RYP&V*2GCy51_HMGN+cMK5aeuS>j2!g{cWEw9y z!%tETf@AIE%HOiR5nXu|%@?QS#=FeEA}~s7^&TNd78RT`mVqY?j261J;N)v_!cr?n zs+yG7_16?2kDw%7?LV!K?=4Q6*0hgULX@R;UGpZ9H#7gu>{x^ci3G5TJxn)En!ofk zrFFtdc|=5KKr}sTjjWi)%+<=iS+9_`2B8dKn~Z*z%NJ%@Z8DA;+C`eCM-%{WcNVwa zlXZZ@cTkz|W=4P1CGzV`cNNsCuZhUz?_P}(Nf+=xR6NTzqg)S_H}D|EeI!LgE^Kv} z00H5G;fqDXO~eCQqQG-<);QgaA~T zroE7DAVQ`+VF74R6gJ+>pbbx749{m`B!vdZd;0;Cn*q>I-r7(eO}*U}buNQC&u_xG z3c$K|?-LEH=` zTo{aP>W3jDNMz`*TZhp#X;u~F+55m!bGi&~#DmUF#&xDhRjA+j zTnG(3{q_%Ek-uW%4s<8FH`le`T9S%|sWb$_TbwBdcUjC%sBAndiZ(N@SDn?!<~-!g z+v!xEaf)wCf^r^aXRdBN0$QP{Nwx-J=+=E=ESJrt>l_Tk&mCs)lrvS)N$19=MG1}J zZ)-mO@w_6}p0|?+OqZDnLh^(LWEo8K4zR_LbY^E+LO5h^-QY<^O0n;ccdEFt598fk z#2h_Md9J6(j^cs973WMV@SSIXmNgW}IZTtqM6gIjpX^Xguqx+b%DymSti;J<>7k~& zlwWha*8M|3lOWzvV^i8vV#X1=nRph3>?s9XC|PbTG^ZG!+T(AMckn4&V&77v)#f&} zh-av!p~kz_iPY61H>X;&bUO%_dMvw8v|b9m8@5@Zpp`Xk&SYwBc_}vdiI(^iWTeAa zrBZFQX}5zNKy!p2O-Qwfh)4?c8LZ~v2vazJ>O=g!+te=yNNlghx?a4+orhB(yi;K z=_Ut4@#ho(r5ewE0_~sg<-HosRQmp;Dr)en$ zbuZniMN0sNXY|C;-955EQ=ba-E|F3rTCoyMB_ov-op}U^avqvn$5P1_(9Kz;>rQX! zzfX1_ynX}+E-XYV{wch11OKmk@c$UyJV+Q{_eZ_o zQ(jzM1eNKI`QZ+NUxe8AdG3febS(m-Gp5TCBF)nw2Nz_JxcV@h_kef5>mcs_4Ttrt&1wR99K>tK-ty%z z>+{-9{$?AcJqL9wF&-4&8(1f$cqRl}xFkQt8hj2Mhdv3K8D5k`888j(+wc704}$|S z>v~ftUzn|U`Zbubw9yMoM7OF}+81{r!&wo!*OtKo2+DktdZ#On7K!0bZb^M-G^CX? zL$UuMj&RG&#GB)@UlZY-*q^_ z7NOk7{`rmJCOg6&5!X?}`j-xVJ1{Wrj~Tcw!u3|0jaS-gR)SQrSjYlMpsTAPv>zuH36vmK2@HD-@Pvz36+M@V zTMQfuo-e0S99an~QMr}1Ey6j4vsR1O9lmj^yx0My#PkGxL4HTdbl@U8-qHkS@OLq~ z+j$jOTcfX2QBjy%OD<3Q1AcE`8uHN5%FCdHvL(-Yq4(Dd^qNInxdFvzH4ohnWt zx;zn&dWu1Pk}@0sPGq|MSjf=n%7Ds)RL%xxIUJL_x}tLR;etRQrlpE8gqqU@deaZa zm{RurfcX6MX9AG2d;i!+0OEw^`D+BYYbb_E2%=9f!ONsnd_B+!?&z;=Un-lx)+duAx4-Sgr{*jeO!OI>+B5Vi_G-o$_=z=XwcMEKyT!&wNW zm|62*9W#_B_E3gJOoM+0^Oa!hU{(_t%vdJ5QbbYE`u%e2I4l*bA0=2y*m5H*hm8c} z)UoXQj8(;1`ceXmI0PcpVHA$|0A3aZhXGSGMCWOru$&u>oB$VH`Dt@zNlj#DEUKCW zm;*yipcKZK41{k{fwXxij^wdl(dM2Q4AiO{fg4~Ne7%$$^2Cvow@@OU;8AVow-sB{!~^CJd8tc66CZd9S9O`1weaQ$+DSzb=MG5G>rTM~<;b>DKT;VVAT3IkBu9*qgh=ELOug*tILs4UukPD2)A1ni7}XV4 z+(i9NJ9jL{&ulA&vJvWN@o%uZI9b>vxe;RU=3Q* z-IW!E*yrlvzbN)M8?Ekc3h%)M-EGOE>AH%5OK}iJ&`oH%*Sr;4Fd`Agk34kUCIClrrG*GfbSoObIhqi zP4nLkV68ZW6_5^=2sbxUc_TS94hRmBV|O#UMal_eJ9wU}%qqquI|M9@yGl`?Q!>88 zx=$>!srYPMybdj8O97if1+{uXf3p4(MRn!K_~C1ypp!ES z&NijubYT9I6d%5?7&i^c>$KyY`xd1uCZ$Qh98&7C{;tzD#f=SE!2W7D;dPAafv*FA z0MS2^I&8;xan^X(_nr36eOItZ!mo-sQ5C&^FdM_Ep(cO1`y}I=CBp|+ps0S=#vQog z^=C*LFW-Lr;brI^;}U(nkNqolZ9$t?d#qk`RUdj&U*>eKFeKh{+6kdB+jG2OZ}DNH z?7pn?SHQ=#SN-x&*~vqx+=j;9cNGl!&g!fXU^AyW@YwNbZi|Hpi8BAd6-5#S`+bH{ zJW^~#GkKv2GyjM;6vobhV|Dhr$hVSi8oBS2Sp|?HZ&5j(6S;)l z8YvJT!CK1AB$kPnBe-$avpR`(0l)3ViIW3%ib3pHUmxHr3;YdB@KqO>lIQl#fOhDc z7i*bDp3gq6WVqpcKlI{F?KI~sH-XNv%fuU6Y5gD<*scK`47Wyi*X=~mgVwUTMGS}tt)%xvM47l z;fZI^2TKOnN}0U}&lUzjaMp~bj*aG0lfkD_a4<1Tlfo1E5_J1OQQ&wa+rTB~ODpj5 z4yle^rSPa~*&2c(L{l);m^N6u*<1}%$aVG$>rlC4niP{ap@m_Lv1=LzwmzO4R8naHL znZH`E`NM-6JlXHUnSb0+=9IX15Z!3;gYZDPwQBj?Tk8Im3LJ zY|iAOj)?d42PF?!we5i_#L{@;fe5UI=g~uH!bL1ar8)#WinJM|L;e|5E#n9Q`BNKm zi2%wHBK=ldVeEVl8JbVEH@9S3(Vf})dJqRRR}D?HS}eWGY9Y;eAm8YtZ#kc_6f+Ry z;wyAoBU<{z>HR{QFEWAfyS3Pt?;x#?kBDk=KfVq%0KPZhteb zp<0pXIochp?;!AZv4jEHSR+Lwc*OExAKMDVFEvfj*1u#%aQ`NHU#k4$Y&B!5Dw2-) zM%uu2XzW*XbfTsy{V(z^o<>od7&@H?T6>S{&qL;6)$nWJJXXc-v3G4qO802{?E!L{ z{>0NBTKWXO$0tih2Yugoo|gWR#^^ZRG9O%^kySF@7K@svEjOsdF;l$qR^TAmcXS+a znxj>)pIs3Axa!wOQp%uc!sYL`NN7H zhWYyb47TNxcm`ZXI7Y3C=*O8UjEh)wlL^LYe4GHZxA!C1IwOo@{N5(O#1m^feWHr& zeGL4Y7q<72!gV|+&hCd|AG+hr!$E`Z0LFf={2S#@iC!a3_iSIgJBhJFhi=0$NZ@kc zVKsEf`m7E!;y^8y=Q&jnM`B3ZBEA|e|E|-VQNPQq^E(YOi0-}&FG!V7hMaKNp?7aI zXr4j!&UsO{dGA*NWl{9rAMRW>1sTtN2r0T3QbKZjaq)!L2iJ4Ou z#t>x1Rc@w~k^CmYIL5L?gzf*LD)N-Ccp2mYoi z;HD`m>lVu6L3wMX{5Qoc8of&I1@2qx*tHR+=My_UM}X!TMgs6=YB&x%S3~g;)!z3ExTw_48|0Gu}At zC$C>eyq$z|$_}dbY!AtxBsetfz5$X}NgSw}BcsJ+OMAw!wkz}V*1-dSHc8@4yDeO! zcUI2mtJ+M8lERgO}A*nm{t_khqpl8DF6rYIG>fl zexTG_3FPcy2_&4UE1S)*`M0RI_vgP0lz7#2k_u)ARYs*7+1ojtaR-DPL7{1o(*sC% zxMuPGdL*V$--nkNxjpo?Jy`0BBr?4YC6!C49DvH{)p43STZQf|N^4KYb4E|N=_uFX zyD(39n%8Y#t`LZDDc16@n9{n|WIUpD#j`~~1X29vQrr%o59d|MSX9g{{3SLY?$^Dm z2i5uwA2+@sX2k1UTUraAGV@Eat*WBxms*Huu4~(8&Onl9=UmsfuUV5GJpEZ7G(&kv zJH&6(S-YUW0MGVJ3Ph@7_Cv13h&Q+>uqg)}jv3(`1^hyZhK%vtB*#nv4;4(JVYQNg z;t9`jxCU1~$VRi4bqr>e+vKIoSZU@<}fk3xIE zADdcd)O_oQs4MS7F)KNSElJNxh_a+*CO91(vy8s>inJPP8Ew+Urfd{*^+|<7Ytj8% z#`2PsIhv1{1eJET4#^kX0eEk>!7&9Xwn@-DfW-4+B9urkjG%RV7of4@$mNCSF3_8D zGYxjC;17|DSejPn%WB=&D7?T@YV|7JiZU!F8%=bYt-t6qse1n6`?hD_?wf`8X?1B= zjh9-^rBbr~2^Mq8tL_vnzY^Su9T>N{hQ%sfW~pAXQNQNN0n?LTv46Q6-7Ch~P`|a+ zwjJ)OR8I5d+8lRBHP`cLxDogLBZ7xL+$!rj7+g$0x(>t7p~L{g>o5M6(u(?ciw&!J z6*cqsv(Ce2ks^=MG4FshRQ>Gfq~YDq-%G0yO>8fIUK7-m<~3=a+#ug7luns{w$Vv= z^KmMGmZO=Aq{KJ5MBQeu<)QVSHA?p#aOWV{#AmLcFrSOzCc@HG&F-DTcPGq%zf}yM znC(;$DXrPX?+1Y^))CT^D$+9(cYr!ai@ZBFS)6bYF0(O2@ zurLOG*Sn)i4s!swgRsax5eoVD6%)eLtjNW6z6h z3$ia^X}#N4rQYAZw>``~s6K?$8|`U!Rk?b@E>QG-yQ=u9-g8bs+<$urH+5-5a$1_F zXeo=Kl;O3eKhEL8rdyYG$t(I+cF%*QGiMzlZT-}FhGcN=FrkqQ^OJm#@AE_Qc+aK2 zYuwz0aGwG9sxk7+y+xQ(+BPl*jboI;!l#2ctxE<=Ma(8IQw{X;Ij&jI`s$@q>c^Px3og_Xq&ev zoOy*h6$?68B3JAeWmh+|q|bs7N>t&Qmov6}P|!VR#jk|5@BQ^SCU54%8lfgdKQ5Zt z-5zBL-6@VleLAIxh$uk?mFd8|ap)Qxj8F{RVS`&Ij~=IcGG_fMMl2+UVlpAHH>vug$H%8RLt>CM zZ!A`xClwN>QqIJ`540{2Y)}{Da-pQ)Z7_U-fHp}Cajgud(P-0h5vVNf9tEU9-7}*|_RGSNJpyua)`Wm9Dbs z6ND8bFn?>0CNiPbz|zv1!^V&!MAwrr^O+69JiGjWq+X3Oayz;`wV8CZWU!a(%B1#6r=%zxWbMO<@R|ZB@?3?%nW3 z^)o1Vjn-vG2}Fp9t!nc)21(8_BO(w)It|UcUvSu8Rh|vMfp#6sHXIdsu$GDJVw?=T zlIwy}Z67j9l)cBlIMd@8TM|1b%pq}ueEUaR!&ZU*kL7~L99F_(2(NDu!%hsY&fMOhDgp{_* zBD8RuwiMY7?8EgOg(Qb>@4fF7t>&oDx6JmCer(+W#kLGqX3f6rTiW{&_w34!e|l&I$yO7uTa{bcOT|I2W+M$Ps=PypZA0B`W>Yy!3fC|4$ShpRx+P&OK^ zU|CVN7?DA#6j2Q%zX(}w*!x}gVj^+ZoYHeLO(x16-r2j@?!&Y7x6P*W-86fG22H56 z8^7+?Hy8-hf3r!yPfOZW_8}KC8v81(+giL`i?X63lgek2u2Z(D~)pr&JdV8n@M#!iJgz&6@TWu8RAa zIpG7SRcvg8RAQ^46<;s`xppZO9WnK)Q_ot{OR6~$WGKD3S?qC~?o5ogJ2C@c5c8b|ZSE7MxAuH@jN}Lr<9Jmzp zK7%-hgFC2fC6pV<_?}_2FES9Ug*M|2TW(9Kr*+;Z5x9 zU9ZpnN8>yii*wd==V@1#hM9~!twKHy>g}>h=*7j_3JI?wB`b&d z76YF*?@sM>Y+JBwb;t5=($nV?OV4JGqODuGG&e?f(RQLC(EzB^z_c3!dsNLP%!!>) z271ZYsb5Lbi+J1wYI~I$2H<_~IPT$&__;igr#{immjuxfPXlmYe<(cm=4OwRegX1F z-fWRoZ2E3#JMGK2H(kC~x{zUxMr7C`P!)9GB)~O)qBMju2p)3Ud;1iqnP43&nfrsY zX2E4!$zZuTqti@{D|Redzi^sOA5+`{gf8hIJlzdazesjD#9?7{n=^cWpV%ygZ}w^J zyX(iO;LEY)9Pc%F&-Grj^M;`jW&Oxlh!IoV5SPFoDx;I|j6a8|x|k{U*n;Or+%jh% z%QwqEfB$WhAEvq(+T*IhC3#kF*tXvh&9u>HG7e#t)4sB!Y8i`Wbz|6x6a)eef&mGK zkLT>w`1jS?tYMS(j7zNC)*dZ#96K{%GI9oX{Q;TSqW?(PwTM{|X4|j}m{CHdvxxkb zghZi)7cEqp3NgN)fw-z=CR= z?@S8d{|cDjM`oH#F;vHwE~xuMeQ2Z`xHV{aS&v##KXqHb1jk~Qa;c_s;>X>*p{gW0 zRxuS!b@e=F7?tlDs9#o$JH&%zuNaxGQZt6Qv@mBiNasn*)PhnYM(H&D=WCO=`a37~ zaw#vfw2ABd4fyQnzc~o*JO2oMS4DtAqyD-F`uuid|Njw>|6R53SAe{=@z+D}``1IT zBD=MjhJS%2!PD-b*s@eEldHFFvBUX4RQrZ9i8OwjvCgGGU)R4HO<;f% zl^|w+upE;6_yCs!t`0Eu!y+R(Y5=XRAe$ZzE^CqM+(56Dp1~X+vK?YN=q&X_8BsS$ zY@Dws@|gOBBp1$Xi1Wm{l2luOd7a00qGL)}C_XjUd~1f6hm+KFxuDoX9szON(gbD` zO0Ll^kTfwxLu`XYpk9lyF^7W0yx&XxT;xGaoFjlZY@qhIPv+s1u*;oJgY5_?@R5qW zI_Q%z;)e!iE3Uv^)C4{%I|@4r#aX+Ox$i5bfuLN^TEJ#qQ+R=Vyc+{s{0QxiJV%h2 zU>17~k0z1>g*Mr? zIC#A78R+^{IUOnPSvmc>&AW)_*-_|9ACY3Uip9k%*%C( z&_I#di^DoG8AHGDYvO<0Ma*a{duk+Jyb4apcqo|6={SZ0auJJj4^2|6f7m&71!9*= zSCMIu*{~RLf_fNUXILnsU<}{I(KLu8*b4QxlT9JxnjBVYaY_g;Ev3oui|Js>^X*c% zgk16enH-hl2re>iuorFPSW@f0;O2xFM;gm3jH8edL6{H40gNk)Q0erI(bf)UF6FiVBzS#TN3w{Iil!h1=j-0TbZmC?%B<2Kwo$L>H#Q zk0TB>C<-UTta1jR>Jrr~p>Jk`jDdYbKyW6l1LK|AmD(1RpVyc!1|6o10XENY2($z| zt2>eiQTLfEQguLku(gXoFw&bTbtJ@zuU*P#b)Lph0~?udo>=lYkmXo46Q2AZ;rQced$zm5-&wwmqL z8jcFCoJCgnLd<21h=FiWd$0t_kQJm-5@-YDUw-y+06+^tNRTWp(HTQDFqqru6@5xg zVUk>oZBQ)paBC%%ev*55_6csiOiQQa|<}{UT7FspSoh;ac6$@)0_E&JXs9F3{;HmMs4xzl@w(k zT~taxkinsMmuTrSi0d(815A35R-M~)VfY-P1{skyjiT9D6vY&l3Z_&@ZTR(kG^bug z_IoUO#~$>3B4CH&3P(WBe^?F{9Dc!P1@qBOUxNWsbb(a0+cg>6{5Dv3F>%$g+_|n| zIX2d)U8T(OV4?Ld@E|K%O*jj zdV%0rdQ1s;|IcEtD9 zd!ZnUA*cqGBVifKO&DC|kz*tYyh@Jwr0ypwk3u~Qf?)i;fM7#bSv@qQ3Evx%$1KeH zb=z(*nNa?fxTCW3pOZd`pdIy{5tUv*kmyOVlngw~Va^`VoMN2EH^;x_MbOBg0u}VdxfUI*!e>zEFq8QKEWHHB<6=N9W39JEn>%miJ=<=Ok zMvXS-g~pLV=-^sGb}CRzfPGe*!$l509-};^iI_hbws^3_=@e?*K=15}JSH;^TIP-7GijuFKeivWMF@UH*ZOwA|)=2sF2vFyYZQ9kIdkemDr|E?R6!2pd_G zLEHl_j?+*gEi!i4-Pz)%5s{?^8np-}ReDsg=#Ds6q6fdcNjYy3?UcQ;6i9mH6NtX{ z!2_uuo05p@&bv)dNT*lMtLgMyYq9)HtH_eVeLDPHHy3 zf;8iIh!jT~7*VTWR9GeNS{X?!tnr%L}2uSh7B6Fv!eBpXxq#Q=Y#>zZ@ zI{cUNUp-oCW}Nowp;C@%Af<>vg-+oe!6%nl;ALuQT_G(zt!>4|-=KN|!Pc6}X*TA_ zX!ub8#op$X{RCv{eq|yLI`$2n(hh&q+e8MemM*Bh6vVXeKpO5~gTXv+>=_`Z zh5q%-N^tD56ZA6A4LCNbWv}7YrB%3ygpR7)VPvnUkqM*5Ic{8 z#1yhuGU6M#iCSG6=I1q&3g?`%IAM>_g5e>J12su7slLPeLRcYdH`TSXRR;&^Ct^f4q+zFT zvxiIv)sXc!Rb!j0+LePXTK16N!bxf(;_+SDgo#Tvh93 zybkLZMeI<>wJ}u=ZsE;KCJF#4Q}`&dSNP-rgMcQ2F$E`m7~wg#mH;7iHTh>xWQou| z_TIu{kY%7}`nV&sR;&xPl85$nr?g9MIxzg0VQS2J@7ZjQ3ZpMHS> z<4;Vg_g!@uE`ci8kDfl)&gJBCPy(77_CQfIMDNsLIC*TDpZ49l$*C#Gtxb?OnxTq| z5%spezRQm@Uyj3Q62JEOyX5?nJWKDv=fs_hk$TYWpO(|u30!v-n-J8mKZU20kg&M$ zKXzs2AGYJuvK0C$dpB-gZN2^({Rb4##-q#?x{`u@Dyely_@yA<+rQqCtAwksn)fY- z=RX{5GN2!jq;RqqUG+tPJpxM{FMc z7M?KZGJAsB8HX85fA0M*KlvJ8eG%aTrySa0@$fZy_+}lo-T8Lp`cgkom9{+L{ngJg zc|X0~^{7&yv4UR>^WL`;{CM9zlyJY=_NV_`&GE5Sl_%GDn+P0R#4W2UN5$EnyKr5Z zw=HcR+VIjzIjC0Fdti$pChZoUM+X5;_JP~}z^N3Y4=&uA5@jm|TGdNr3JRI9t;{>? zkJ-yE+l#_+xi+GKAa4wSpppA4+>KjOc)mD-WNSC0o{6j4Ddb+fW5eZq^5|lzcxbQ{ zw=>zE4usIqrRQ7Or+~9w*#3Qp#Fas<5M-h-&?->&%?vd6*EP2Ql+Jt<$7a%~(axk) zhrMdf@mIFs|0+Eg~6)?_$-{)T&fa;6fq)KdcrJRo1aeyp6xEhX2NjqPGcJ`?9T2ch{y5<;9G;Xx4v*$o5N{8eAwvBx zgm>?QC+_KzIV0I|^7vpwq%m0<^V}}ST8zfDW*I~|bV40bR<%Kqq*5N9{1#GO%Px_|YLd&Q)7tX;M{ ziisi8xFY4snPZ52tV-*ak15jw<@J5kG`XMqihbi7*#3iS9d(C>sblI=A|4fhlame2E+!90Dwbf7R2B{_^Pu>ysDV5~Mw)h# zV%&N1qB#~CAzB_k&bH`Xt-!md!*YLY7@0=1(nCeB02MN% zdwh-4Nq1~iLxmKj?!Z4swwCXz30e@9KY&kYD;U8SiRK3bF44f0qr~clCK<8ufH@Bss!z-CT6*;3bS3uUc`iFX~ zXLN3|ek5SUhI_}_wHVeL7TTfEoKk(#JZ1noa(7%|)^!z){Ev|VejDBX(!F9Yi3f_{ zSiEz=6l3U`4Ah^-YB7VqGyR*e8ec}Bu2(?4H;0Fzmvk)6&QlA+R#$N|jx#4iS;_ah zsC*$coyKx#^r`6l2g4yu0Nz+=44L(}c2rzu44jRc1@SL>N}h0!h-wXBM$G2f^xd@; zUIQIMjPK+It1pm~ z`R)Z363nU0VOwdv3gi?dX|xWc&+o%b^Y=-M5S{eCtO%Z3zR5aih@po;C0BGM;ny5H zat@-!5_-p~B-mVa@U@<{cofC6p@};t>!z(%3d=j=j*RxXQxOKa@662&hFf@B#`A5id-m74@3~HUS9Mm`Z3=%8zQ6&J z%@vCKWi=ZHql*Du&LD*FzGV!x_3JK{Z!UyO4CTcREFHN#)ue4RocW1&&Q(VR^jA1tOgx;6BeDC`HsrI3nmm(~@$J(nufX498JJGxf zNL53&Xp|Dw;&J;wy$L9ki5UsSDyq!Z|Lmp%&W!vp5iv3ArWDQ>Khr<8b=gNx z;;)kWjz)cTaihw3JdG&jF=4oeZZ5ytgdO{=k;EvZzYjYsGCv)XJ}Wlb_xaJYy17m^ zj~X^k!iv|A$NR3Ers;0Paaa%HyGqx0{oWrxKeNqfiE7|q@+OckUe9O!-@ovGzUusS za^~y?@b8Ts^#RYTH^?qW3vG}LdZim1ZQhbu$Fx+g`tmM?J7jxV$j=j>+Kwg%TkXvK zIwmtw&V1i*3Ad9y-P)=368rom67l_OFT*y2{l0JG=I5@s`l{gHrq5*EPAxhqHxJtB zo9x>plWHbEnY$^YsPwO#%JMgZ+u5@^t?r@xK3?aGc;+nix5+L$*K-)UjI!!7KT9mb zZmihze26673N=;<xK!KmGv>ZEJ_=;kvK4`t{0Ic3KT8@neRWbQbOrA4s084-=7 zrGPw$O>{*Yl2h`{8oOt*s7=&+)jZbqyc=v7SgP0H=Adc6_y1E+LD#S>s|1WeXqVHn z(UQ>`@}eX@>Q)YW?;w7P$GrwrIdMk_SMw#o3Ud>`XF0}M>(URih#q#OY4mRJ74ed> zM%t85@3Wow=ka;xj!%f7j{nmHyp!SzR-Anc#}QN6tUqBA@dc$lB9{&m%+oAg*;wZ4 zrh%JPP02=W9>xKHq}Z#A1Adfg#b7p8%P8IK^XuZzz50zuz%I8yn@nzNpE)>_u-_Q7#X=Rnph!Hh!TvH zBAGxTijWqF1!ImtAO?^XNCiWIP#^-36bJ=Ffj}S@kP}Fx4SX9{~e%kRsXm`B?!sQ@0sdBFX8-qO%L&@0&K0WK^kpWw^+|!yl2i$6jhA9P zQw;V*%RR{yqhwJ??+EFrWNG7;v)qZI%aMqsP)t))Q>owgkn-b83RWrqa;J!44z;jg zX)u*V6tGDDkxEr4mjg(G2Z`r;CFy2&eb07{hn-y zvlR%e-5Dz1}I@|Rg!>H z7?^z+N#;_e#ObJ$jF?aGgE4_>2qYsgeXpsNgG!0{0bZ*#sSNE2?}X2;Fj1))Q+Qm! zNVy+`waBl?C-x`7LYQPNS3#&jlTX^38Hq)dAk9TyCokXt3T-$TG>3_)OujjHnGF{R zoriV;OkoQFc2f!_7`TwwMvG0FdXWlO6x`I&7HC31s&NZyj8SLC5}CH2RdP0Tp3jku zgf-h5*c$j|C2_VvQ!9gsay61-k=M}_C{j=fM7$|eSR_N4%*#lD1~<&kj$|gRB;J?R zhN?Om+xqmChE{gN1&P2>9T9w8XM`740c8R8A5}HXmd_}Q?skce0poN$IqpvjzkQIy;%Ny#y*T4bm}0aztL?Vq7TxbaJliQlG7a!Q~is@cW&t=6lsYK%(*|DV~#_Ls^{SD7pANsp`#y=!itkc1}SB6m#vvdWecZhoNY96CK;{PU2wTG7osVjasgBo? zQq+h<^A}Rc!DL>pK*J6JBJ@PXY=8*7tJ0M~1YR;|OgeC0XGd&0uwFrjX>2R$Q0Ra1 z=p@=Py4BFfb_@gt=khNzrhZCUSDV(K_>uxoKFN?IAmuyPDBxJ#SHIH9-VUi|pz z!!GB}o~>F`JA#Ip7)5t6GVz&aIt^x+Eocp(GOn_$M4O?-#$v&ZD7`0dbF^Hq*);Dt zw0D;_v6aU>JWx7em@6>~HK&FyN^@EJI_6ms#;9C#EidF}fE-RRfr?dw7^@9IhUKtY zZCp|b)-XQ%d@*C0r!rv}PMp6-&SVyfVH0xhU)Rq5e$tdAEjcaerN&r&Syu^=O381K zLmdagmk8L;25za}tp=3ROC#)D50u>i>`02Dt$^q8`v`|)k!f%-u?zf&(>T3@F+eJn zqOk<)EGlDohrC?28Emoj4G>inxetAEHH+nBh^ozSW-0|Q*E5P*lc5J8k5{I4dPKaf z4t1lqra99AQY`9a5k{zOwphsciUmWbW21DKQo zGJ?SVUJq$=TalxaRqGPXC>F=xZ{<`nq#_vWFDh8u#<=K(*TE*T1CdU$zbwA@ zmq8f6`sO=6n^e2$T7tc8br|=uwXds0tCmaDRKF3V6m_MA7c+1uENg-H8>={t(fz(-+ zo;Lsy^K##sj)Bo`usV+vJ;aOKbenug_IY<7Im~y?eR|u=o+mYM&a`pwY1r+fd;(rWY-6 zPv9+Gz7YMIw1{Gv1LoVDq%S8mN@w3ngC`1kIS!2Odxw3YP}K7Y{N(qC^sjWkwf5Mu z+Q`vOVMyPF>FWcb4`pZ6<~T9!{R{R^;2se(ojx6+o1*WDEO)VvfA6bj8zxonop&|A zip)`(>hK)ojjFl{4ZX|?$!$;11U~3l-ln-8cKoivA`0u+G!3cCQS)+0f^3pw*$N4A zjS0@P*k!Z%L+d_iEIRr$3jtzughtO@7i-wrD|^NTD#cP0-0mb&B6wD-a!jMZBo>+bX04WFIc+X;30 z?zqedahQ$v(kbs{UwhECexk9iQ247|(|We3^Fo}mmOTan_==~eBiPkts9Ki^VZ?|B zok>f3`EWxVS^>`M(z9r*W2)DXH4#=t#Mw~4)}-W1oas8;?kl~v(JD#5-BpJR8&)S9xfQ|ayIW%wuFL@zu^VDpO_j_u?p#uw=ZJbsRURzgNexEJCQa8+r%cir=wg0pCWd zk*O>B`B%|yq)O+$scg>tiQl@mp)4FWYg zX>*~}xpl>!+dKa(avasF~i$b2Zf(JK+d%%&FF9_@KW~uo$ z!P|+l6Xl`#d_Ry(Mv_>oFP%O(sr2#$x~L{ht4E2G?LP9UqGH?lUpX3QT$SGjqQ0c9 zu_6S}6$C@aCNv#~gW8P*br4bAE8W*}cRNR^X|J2R+PdB?!-*K@bbCB`=&*&7)8nkq zU5&za8=kgtoqygC>&pXP8T*FR%=g-_p0jN~9-w9xOZ2%amIt4N^r!ww_2hjsfwo|& zQ*yg&c2IinT8^C(gpEVjaO4_yIhjZZlnpU{;th$h9OPLC?~~HCNka>-X?ei(5Hd?V9g|t%fIr43|}mO#qqasf(!GHa}pn$JahW$ z2^t)Qr%B=DIn_M+4uh>9k#TtiOPMzfMj_O7<6+v_PhDNkcyVP}eObC3U?12l2+xqi z;DlrtD&jtjyu}`-;asn-zsO8vnRvt}e>*gVhiBb)Ia~PqQNpE}!ufxs%_BQwxS>Ss z?AQ^7OFrQ_K*Lv{>mkWYfQIIHm2|&!*rY86%s$-0Cgx_-eYyPTMT!Zh8D0~(oMVzc zuky1w;iG7mOY82iKgOhO`%)6zDVxgzYaX z_O~dptu6Umlt}6QP#;@nn3Ik~{rFYKVLiP28^9RWU=NE=5s`6#l7vEXqC|V-pGQwY zhbX92^6y_O__Yvng$E+NUN_;WfiTwIO1SyXp zK^LZf<+DEA+gGg~gV6fH&8(-cd05u4{zMG%59_YUG2$@^$<677f(?4!MUzX^Q`&G@nC)`)r%T!jz1h;Cbd&n#RM1i<#HH& z-Cg6!p_T4(*Q!aHeUoWU&r%sTjYdM8NrI8BBCgt;x93(FxI>34bLyyWXHBlUsj6Aq zrOU(Hw}N2J#X?qdc^ihHA!{UTzy1=T2F; z{Hx2~Ra*z1o*k2Lo>#J8kMXt-kJ@EZ511`XA89vO>L1U9zLw%Otr)!1SNtd3)B`Et zd3$TuzM8^cfnM`13w;e|1*WH@eP@7pUBY@Zxi>!D!=5u!iO@(oM!e6U6A+dz?&Z1i z@aOw@$wXaM>XT##@7=&oc}`oq_LFRbQ1tVk&6Ep=cOU$I0XSdgOc|BRDlt4n}f-ppv@%^rV`20JUb^SP2Ca3A>TLUe_`^qDpgjI3UFrqX+5vc#& z?*sQ5)>=&Mm;q;L6u>af#TDc04f>M&LvgQU^@V5Djg z)fiqSJ?jWCCR#d_N-<81$aDsmhz^uAXf?|(KRBQewHS(Nie@Molj%k(GchJ>k#3S- zW&{+L%o|Ll69p|WB5#}b2U8lBT<7v4iwml$DOvw&N+Bn@SgNFpDBFgd=l(GhRFblA zFask(6^iWJBKUHL5@7~DeUT}CIvT%Y6u zqbuyysz6MZAWVs*=F;(skfC5Bt@9R%9Fif3!5XXdXRFLQ_za=AkcbI)5XtoOSY@78FR76Xz4U3&rjnzLqeG@+H-lJdQ5!a} zkrC=B7@5&kd`c_ki44{6jQ(N`wNumW`ozBg|{nTXSovm&*!Ws>yFXPQqXl7u?j z5-<~qO7o37sTr9f)uJkv`i?*W<`8NQCe)mS4@rjn0`-j|@(SA%80Ay*fh@}Lk(`aM zNM$tgUIf(sMfXVXdLSy1xl)AO$p2!}{!JrgXE zj*8ck1j{7a=J-j(#?Ho*5nIcJ$o%e2+0>ZH6o&GQvJwBD6{j9oj|J_IAwhSUPvsP# zV3N+uQ^?WgJ$BVQpFpK#5vp{V4 z==*S6)cV6tK9kMaZ}{R};SNG8h0s_G1I^oOT|Mrg!yqVc*QI@S{cb2s&daTXqv z>DZa2zQjv3>x4}{P2J=1MWj|abYyDo2-D6xVbY~BPkwX>HtPgW4o}^Gt0B;y?mO`{ zb@#!FOcMWOIrr^+7|llDn9ta698X^q@9^?fPqNU*3R=)`LRRpjy>YmGiZBd@clV;M z;Spy4`yn3~|6YeEGcy8lc>gt z+`50qg86{hCklSsjfQ?4;VM%zM%f*(F+tl=F-F-Q?C^)#N>!fJ%M$Vm4#cKv%g5F` z9zCp)Dd%D+5{vLK7KRGHzC&EnK_5KqqHKu7#b^U&Qa%PGZZNh+kVSNG=dn%*!u_bt zot)kF!L~+3;T()&xWh67wpuzE8~tYqAgw{RC_@y!V*X8v)4>tNN>@BuEVrny8^#VU zYe;Bjvd#yx=R)o z#f)+gLs^a;{jaQO44crw$vIscUn^xwa%$3vnGl_D7Ths%sqwLJR`A|QF(Len@vEqX zvPNV?=Glo3FuM2wn7f!5tDON==Nxzsj5H50GS}YflqNo4_#Y~8R=L^E~nb!>^I)}|NoYF3&l}A>d&d^RspwWd}5F1O>572ru zgbCw46n4J~2k53qiGg$1@>13IM#(Lq7!u-gFc+PXJ*+t(8u}eLt6bf@da=iJ?(2`# zj>}#Kv{gQD+|u>6>}EV%X&5dcX#@{S6%v2I;&srT0b9P_6D)I6;}+l@%*c=qsCgD0 zh6uO{#|_5(3f%nQFOVs#D{Mg7t*75xub4*#bN$eE2H}e)=_6_YnQS^<`Un&lW}%ad zd!lhrtNjRbPTo_*4(VGs9Yl+W0|sKOJ8o`;FKIM^(hz84Z;K9rKc?kS)}72{y!Hel zuuHToM>n#l9Oiz!-4VYhXg(#<{Y zeHb&X;t*gvnA063%VIuaKwFXeVf1;`o(%o4e16QB!&%#0Uk80Hj@PFdN0OeD1l+aA z943Z9z9;!2CBKOza@|P=q8l8S^DbQBqRFku%u&|-RFvwF@7J0@-P$Hb;dg`qnKylU z1*Io>YQ)J~jzTHRO%M|)@=YL9h|zBVCHxJX?7tzy4?TIj+yg#YlGGbM*>c=FehSPo z^Q+^$bHk7GYVnGV{w8f2ekMz!<0>@t4AamhsecP(ZWZ((;{&t)(byT&Fyz!_5%PGz zPn*Vlneb=GEqy$E*o~^`)uGV%jFcaq z(n8Gs1aTVz?O6o&RP@}+W_Uih%}{hYl~3*H=DUiRR~M}(yy3I;R;ei7Ii?eafptR{ z4P(k~1D<}r?D?=5GgdRfR;)-@!f(0qrx6`=qv;BMosYUL%K6+DeDTYJCY^(8#bY~L z{>1c8^!q3;_$oc!3B$f{i)_?lFV~5yUP=`i@HWwEc2Zi}==G{@~AseRAG*b<`OCIORq%2b=-Odv(CfCn69e_N1upNvFk|NZX)*Q$2IGE z*$W)K-1Y}IcP9s5vFImS1Uw}??v(sfn(y-{e3owO8_eJU*7t9p@B|fQrT3SSMIU9X zN+8m^Zo^g=fjl}JoP&x0cUhe-S*^?H5J_;j#Wm`jjCsmF8}~%HW@_Zb9B-HXH%@W9 zuqaV<*3CvwNa8t8bRK3Ggm`-6ZEGFMzt);>(6r@Szc`@2Hepi|-8HP>kNm<8`T3qj z4mwFzA(xr&evxp2OYHj6*rNh35g;x5`Odjvcz|<9&h6ZD)L{Nh8&+>+eq1XCEq6$y z6^?77GIt$(S%m%9MnZS?&%tco!le}4KeVKl&lPL(PETu*<7X=Q3+9o5FKxFjSi&3s zl0#%H$FK5x48=zOjC5Q!*hOSN8RHW9CaKmph8-hJsw`nkWuYrBf8)}eJo@e5fZToo+LEpuBh|vVGDQ09bOf&gdc^YC~DYqm#z&} zd0Q13#hc3M!#nEtJTpXjD~=p7dm%sP(XBo{n+K%st#{~J2SdGoSXX2#8`kc(a?aEL zPBiS3FFI-e7XYU~Sii1SAf+@kF1m}xDVJ{Eez@}7dZ|)=#gXC!-LyeX%4^bB^H=ch zXONA$GSPgD_g|57kY4pt>`cIrsc<2;@#mn~9rBFV=6ZwC=U6=zn$jO5B?VRfqCWet z`!CH2e*iEgMCcP;BEGn!_0+4xnV$P~vAU9q9CtHKI--(oc7DzB8Ri^tN<< z=e3*XY;oHXyDn-(pD=u0;tJ;qq~pFg+^^GbnUpu(|0JQ`-CU%OyypEJe@$jr*kva`$bLyMjc@;toYJBxQTzn*V-y5F{QAQXV^xO&uLi zEOev0(dce8Uevoce_5b6=-;ZUYr6*5=+1Wn$0ud9_}i-f*yOjT4*9O% z==<_O!GF&WS=nYOx|C_wpzf5RZ)$uvWdcH}xfJu%b@le$yZifl2Qv((YHr^Z9IJiz z_wT>`?uY;SZpE=_g@4c5{I(>dahan1B`-Qen4b_X3dX0X?lP2@?C<-kDN^)x$E8F2 zkLc@jTCtj6A93dpdhZqs=TKz0Ipz=Oae>gAU#jZ7Mc!`lNdj&6*|BP}rBs5ClqRi` z=51Zzk6YB?eUa@*Ns*V?>XcChZIMe$4prG@CHZu7qfs8|u%a#6SKW!@obohVb=gD5 zz{iT#ci*`PbBaYpuu0#PZH*g3oR(7TReQo|b-zVrRWfn*`0(MjsYqw6;9C2tA^pTe zrF`?UzI3a7Q5`<4itH{c)MhdOt#+TM-HGVRb-$n=&v`jCI&kX;TDH2+_8)RWta@0r z`7e2SyY0ErB8owt)w%j*8iPGH3?edax}2zQxxg*a*>aI)9nOn(xj5#x2V8e~RkFV? zv=5I}MU8cF%5cj5Pjyo-7bU)1F52usvB4HoMwc|NmWu-}?=T^MN4QlgZeFt9AC&Y) zgY0x8VMb?mKRKs_tkf;4LPKzspq4+#uV_o^;HmX0WW*}d{^7Acv9Q}Z5;m3q>5^QM+ z^9=m3(ws#X=A5T#k!jAzyDKN5qp2&}*s3JHl9ER5^TUPwGBIAAas9vCA`ua3xo~c) z>bA&Mq`XB!NJ)mloc5Qlqn^PWp4xsvtbe(n_CaC;?&~$TdD)92sd=s;I(Z&lX=fh` z8l3L(HiyDxSv6-|NcFc{79Y4-LG3r`K^h{wi zR7^sOUPuPl!v_*DZIXXlsFaEDhf|LXh4Fq!n~LKm3VS9{AmveWJmy)ET4mgBMLk}! zO0z@NU>^3bs&JsJiWS#9dbCI~IF8~WqfHBc*L{Kn6;|!*bC%{9)lFXZ{=ohn2J=_0 z>!QEp=elY-%!g)RNH;LX@m(3&O}y%1iqI$WiT<6AQ96QlS* zf)Pzah&|j@c`9gjG~ejys43%$XCf<>hYaXUXc4{V$&Z-YXan@}*OV9<(E9-IM2GXB z0LuL2vwwpgv1;lQF)ota@dgtf)xG%m$;6i=X6jZ1rop&MKU#*EBR=N^QP0hPX2o4b zeF^=LU9y`c8VZ)^nJyW)JLeWelUg?zfVks#|7-!fm!maBYSwF!XzF2 zG>#94-2(6p>R5Ve!-go0KorI9ZZYj#EEzxFu9#F=s)b^f0n<=_A)Tz{eO=CdZ#pOj8ZPE71R$#9q+Z;+$Ysx z&-HbLY7TirCK*$`5V`JTKge+Qz;Md2sqQ7`AoH*z%bOWopQaMrafV7iJaclYlF;X+ z?+*oT+c#u1t#R2W2xR=jgaDOtr%eStF0s-Me`qGX+~+o0OB*eUZ+Z*C$Wy?0Z6Wn?b7d8RDva;g`^V8W8XBng;Dn0y z)y^T{KeK&g&GrwPNF0sxuw+H*FFvq9uN zQ=2gT>83=9BU1@BeIV13j3F3g2Br9c<0+#A$RJP^>RF@NdZsy^BfE@2XV4%gXwI~DlsFke&L6B*eOmh^oNh`GI?AXH znRF1SDUa2pp~>CGSu6ekHOAi<`h@9Ex5bYfnTiW}KfzI&>sf68N&pgdXkSB(@e)&` zFoT)lf1?iU;OM^w5j% zwTJg|~x=XzAhh!uslYpU`VJ?a$qRlh@=ou#VX$AZ+&J6!aq zB@TI)8F1;)fpflyolmjF!4pyj#T-0r?erhb4IUD|-MC+6VOu=+xGD4URzW(rNgM?| zVHsaJb2WgTy9lnyOJy_DP7tSZ2a-G#0$fWROI`K1d`6d3mf9i~z?QoXYem zibkFlnbiGsox~f7dV4t>vQ|YR(L4?}GJ_sV;~`2-HbJyr2a&{v`XR$$pZZ<;f-Mpb zILw6&Bq@%u;zL#n_mRy&rk> zfrF%zy;zq5(OTqx6|da??@~ZR3Xh^iZraAMr*bKrOUYt+N(l`gWO97$?MIzf3jL*M zhr>^3G79|9&#I69Mi68o^z+jXiE61t1Z5HtkVvGU5(ibKBzsHK30@8&x;nsmC7&cV=kC18OeU301cNP#`ak8~bmh&T5) zr&0h}r#iXb`Ou^6LSO#qyIzQXblq>fzsd0@Dbt#Ax$Ry!OjStY5L765DH zMDjLK3s%jSv(=?X}Mx@H7VSwQup7huT zf}PLg50+ zdZ0;6M1N%A;n`GV9aj6x9PEn0c$WjbM`KLSuA4FsopLpg&pkUWnseQNBBpY>9O``w zTB_eesd3xVAfuO)ERqO!&TQo?A_*=as9r|Km+qt&LZt7r?1NrbUe5ch(Mz*4&JEs| z#wZdOOmsCEh|HL1A(^XYY0mEfFofxuqG}iF32lCm+vqB2thnZAe8isJ#2v3+H83+} z$c6=LN*t+i#VK~hBh;IC67>J=^hNA+;?jg|;P1zN=(vAg(ou&W#`l23`0ggM9{Ybn zUG{uVT_H0YoBLa+yphb4a6>OMv`dM$TrNxgEDD51^;`<{TGwY%ki3YmwL`uHK}L^) zpu&Hqp~AatI54F5Gzes8$-NGO2;YNXy$3>|OJe~DZ-mupsl@zk1R4G*?St^%6&}j0 zJNB2zTgOY}2Wx8L@#~#-@!E0$oZoPM_Xd6c-FlUE%_PWW>;P-hHfBRE-PQr z*nZ?5hGvmUni4BRx!9bbCRh?H+$`zU${viWBm2Z@A@c8;-h@5ivaC9^C)2kRE^mn$ z??3i6mZ&O=k7IJwTePC!aNzhKRl`}5w2NNr?YoEkiCAtV7_)bhuynfZ30ii#Il7$4 zh&1eTht`4W`}3vf@|vyF_9e7|Kf#F+$KXK&>H`SU_c8<;`}#M2ql6I$)zGM9hx&|e zT(KtBLRUzt`z*Ef#ex3pjOhA=6vu~Ri+^2;GgFs6Pp=E<4?S8oKCC+zHgziw511ey zwpg>ttHc#EFI>i=k+T{)PcYFBVQ=0E{qWVvI)&XAvyiB@DYDBhH*mvZwHEfAes_ zs6_hWkkTryUG0#d&z3CnT#9W=2YbB=Mj9;6?5{*`3Bc!0~!xCN}-LCay!xoG#+S_0vjdu zP9&gl-PWz9uHJ-%EM2!vt7$447lc$#el$)l$>3p|UM+p*xg`rNJt@F-K1mYAeD%Yl*@QEQkc@|`dCdW8LACs=B@7S`}Ypr=BX(Ps-7a(TS_LYG~L7oURqd`Jp#!s^}+u6<76tchXH5X_Gw24ro z;sC)$x`Sq`Y7I971{`n%nCZ_7<#ufa3!8qT&@abR>ovjp&k=kSb@8wG9~M@y>40rl9m{>s$=tI1>R# zLI9$Vbj22|XAM0Z496V?W7>j2+>l|Iu-~Uh`4X(OP7xgc98qS}5)TVgx|+h64=&=` z^-BepC=H&YNE^C+$g3;JBiAMXL-ga1F z_Ps7#z~Ruem(b%7ZvW3tJ8q?w>Gu<^xb(v509Ow5^<`PaaeY}SedhYIg_g0ttPE1N z0Vzu8k6z)rn*-y1v`+oAu160SHKz}%tLm1$+1NLo6lMNwy*qJJZ0Z1lEYmPps*`w9U9UTq7!#4Of2?HVZln~aUE8*22&JnsRsgW%D2#%I_mrjDM_;j z5~YC#_2aflke5$;zUB1VFi4O-9bOlp9M*g`-=E(8n^A;q{>+Gdj`)Ys?&eT;m?<>;orEXzpaNU*eDK%>t^a?TSw=mBR0Dn zxLL(0t+KZKvO_0)m#J-Dl2ns`DUjytWyfx9^#uDHQ_$?m(i!3v4VGSzz>xYqaW;(z z{tZ1LhK^#d8TEbeZU{MuE0dy}`Q0wQw9*%Aoh56231SXumW=u<#?vc>osz&4e(6m+ zIfTcaX}lRJXG1L`=goWOh&QP=74OsHg?jP#6>~<3zi|(Xw1k!MdAC|7y$DY!@9T@z zYK??mEK$)xJt3YPXk^qviHHj5Nyw|38X*WIk%Pd3sGff4lx=XCybT955uE`Dl&OOV zkO#w*aXn3#!=JuP{FG~8`YN&7t$AwpXP&|xX@9A@LR4%P%S4s39&a4;HDqo6W546_ zyzY3qh1lQYs#0wFt!brD+Rj!uD9EBvxiSg7Zty7v0E=h2R;eJ)+_BV!o~0`gXXsAc z-RyI?{-tmemzN~_vF+6KZ^wFz>~)k4Gcl@+FuJ5w;JVGWBx=^U!JVvb*>`58g5RD$ zO-I{Ov*W$QCfhaCjcqq;O%@NXc{eR|3AO`YeraXKm(btX11xm?Sikfdi~fOZ&dS-C z%xJvEcimdXO(x`A*wOO{YSPMvr;f#k_*pcOPRt@2gYbL}HLhNX-Vc{=ZOY;M(sq^F zw#<#*U`=5d+SiWnu79hc6dc4~5|D19igyK4Sx1f$rZnYR5&m zo@Ix@vge<&M-^q_725+2{f3PmQ)kHAD5D>6O*;#{6%`xBqol^qVWuNyRj{~q4beH& zkt&1#AA48#Bc-}6@(IS)74Yj0#(mhD}f07YBe-iP+-0xi(q0u{+ zL!+;T7a6-0Hj#0t%nFz<-5b^WGjTGr5Unz+gc_1cL_ew>a>n$k9+htz!w*)>(2Ra( z)>q*R(J-1a+U8LbZV|6QQX(YL9S5gD%ejOGk?oA`XAm*&uTMmG-ZNzW*kv(aTp&!x zqP(7kB?UIa!hB(7FK}dpi(;TmoAjlwS_rha|F?}K@(tsj&Ob4LF4;wG7zw77&Z`>3qm_6zkvRsr>q^H=0pUSfqwqzxt!7MNTq{spa&#I`{a(*nt5j+Xi7 z1s;_7=Ox}$Jbk$QpX8$*R(V}qqw%`9O5w5O!P0;DhyHMEw|fQB3=7+b-Ekv?d)JiZ zdycQev$Aizqs9gMF^lI{7-~I~!5w}D= zRu#K^A}WBID!Gs3qlz&i_y9J22&Mg(D6T2wni5>cX)N0bWIG|)rb#T@46@BAw)0rF zQ^=nY-6XZjj6u2h-f&8h5e!5kNs4F|3oiBE&>-(KQLaf58kmNFU3PR3L z6;ib7$e{02p(?LG2!2*cwOHi@E3SwLM%7Y;Huf^It}mulQ>;^x6;n_IpH)^()67`~39bss6g(uo@gjo1$KK+@B8j``y#q_kdQPLh3gIfgEfV zNpw2-Pp-KScY}Xt2iCZn4kCDY!#&8N9&jBF2VGBTb_3oZANX;b5AsmM;aD820}H&q z>S|bQcPi?-+#SbN&(FhkIIt@|kM`SIL{(x!J|6v7Cv#4&!Cf zj<&n5>W6B;{*EjolFTm7IzK1wj_oq{T>&Y{L&00=EDF1fD6#B9Xp*4HVhB7%up0|H zqP_~D5>$RAe{6o2e?TC&0EkEDcYe{G6a;)zo$QHmAH4W5ArXV8#GrUS9kwe!#VBPk zViL&xE`Ew^4k)V5{_AF65j3+D&~$^&_DB#cawyiZXo>veG(iYP)${)Nl_JYv^-qV2 zEGLJxUvKMYieLe&-i;-7>}^k@jB|&GY{SIKF2IkV$zjc#PgM3ftan>IH=n6WOvbS0 zY&%bfmK4n-$7q@pRh3B&tKY2GRQ|bR^WEpVs41IIVD(qc6P17Bw0c_{$X+#tHQzMP zgnARvb!|f=ZHiSI(y*(MLR}rwv`tZlx;ms`c-f5w%FZ(i_Ie*}u=hj4(>_F&VLI9F z*lxTK1VAe0Z;n>mc2!qFG=Q|iPYdFKOSW#SLl_t!9YcmdLkM(m2%8m+5i^8nT^CP5 zlz>ERPIABLhK+|HSU}RxO?`Tm_V{+5u}@9 z`Z-d~k%&HTXQ$dAWmow?nq|{`3Ze=^(+#yg1(5~N=_`FHNC8Bv;<;*zFrWZ3wwo&q zCr-s`5`*#?LbN>=HR-lVAOU22z$r$hVKl*L`S>^tD1ej?clk6<7*bGD5$7Q2e&EDy zpt=%aP};wp4#(~KYZznzHG|MFyZ|C`3@)T62`@NpsIC%WpxqWLakJv*ZCN#8q=8** zyE>lQ2&92@)o!&VysAWWX@laq*s~qwpJ-d)`T>+h$(k|@wH?G@f=f5^|xvj0WYqder}uK2S9?0 zhd79A(;PK{(}9oPNR(ORb`RO^f>aV^0Hql7hDftHLfU)^kQ7bcYm1W1dPEq90fmn`v;hKyH2 z5lTyr7}EK|OBfoaj4>_oFHvCdCsE01R~FN1v_92!7?f~Yefu2=N{ig-<6%s~`Zx(j z6HKukdbZmGIe3|3%BjAr>f*VG=&6b9at86!Heh)BFD_AC73&}dL8A4xt%3*yiK?&N zXnJ3T(FY@3)y*No^MRytl`#lj8LFGkG1x^w4lat6i`zaWT>$M%42QxYy? zBDV&rwaSw>3TIrhp3e-F928SH+=vfC#4ElIb~t{mE6tlY2keid zi>1Je3sSz5>&|RAC3U+0Vx|cr1&N*$yg7M-H%Ir>gH$|XKhqlv9^k2mF7P}e{+vbB zi)S=Uz1=_b;R-r#mPDR>mH;F#$B6Iu9c~%lwASdr%m`J)XxIAh%PpI77btrNf*JI? z2hHB}Fj$D2FCH~)b$G?iScUvx`;*o+)81xVmetN|!Igd(m6FUJM~MBJf4CvRXB5ArOwhktCUq zSLq|V9gLeUQ%up0o>&L%@c3PakV8&3U#<8*X0zqwy@!G9COxrW#;;0Y|6@is9IV^s z`JLqWe%L|qJH<7?_A1eutH@ni85<+aL2ZQfQ1I6uvCaZQ_-e1>6eW;}N`^lv{;28IbAHjtz=oi~kBNLka0lf3| z_KUbUUB&6JT^%FZ7VfYw7E&z3UqXcoIZ&s)9C_$H_FOjU!3@v=iaBO7$4G+4Gmb)s zKBqkpIxL1;M=poDNkkBM<5-QIv6J*a;s&}Z^GB~7hNgiCJb9Ee0nQDM&4%gnzem#n z59i|#o$uQl!c{xN-mSI_D+)GP0#$_toE*_(w5bRKrH7&(O=0=?L+A6DLScj=blrD3 zgytQQoS-o4J{8r3vEro%FQp`-z%k3x=ekxaYxJy!;=Gd@ucd7L5QzO}_uawUfWer` zz(i4w62?TJ8O!b-X$<5??M(G9yC15~85-^De)8zIBrG3)=zR9nk1aVrPsMiSN-cso z@~J)VqUMBje7?@1D0rZO7ki3lI)+w8cczT2ct%#YpHTc=EkCfSBRCSZZVtTeZb189 zzzO@gWz{ac>+^~$Qm?onb^6|D3yw>_of@^WV?oI;JUASD3mJ}0hQ_X+c#UbdmM<8`9;a3D9cla=sO{T-Cq+Ae~tMb4+r!*7NfW5@~tYG(f1MdFrQAR!-4)^a?fwWrh@X5szyGqci41y&VJ6G zwi0$cRP?VfZ6!F$X)DP!!1gN9nybjEX{!JSY}yKOe6*i`XLS<$doIh+zn5$F^BDf{ zzmIv9PTxCo0)5fT3Hy1xscZHsGkD@bX7Gg4uo=8pnTRq&@rS+4!~+BA`=QK{Uhaop z%bY(qU@n2Z|FE%tt2HO~Z!u9X{z|-arDqT08mAE>f`;sdv~EtZExE2rVtv22O%#vj?8iLV#$EZ7bN@k2CA)J z4LEK(hp_D6t17t?AI(HIIl>&oUNxM-sAVH^u6QFiJ0RN`zM8%I_Qti$2i!QoJh#12 zL19BGZ@@!_ZdU@s)tveB+MK_=iRs|vq65^m_HXm4-@(nN?|p5dIAPi}(j0wQ-YYh| z9&;CPvHt?S&Ds6*_5*J%6cXVDCc@|}=Im2uazsY*sobpsYdOCE4r6>Rlc$zuB2`Nb z)9j$c*2m6Bqqym7czYsyG&RUwg(dgX@1rn2s`5;OgB>|wQZsqP@0+sv)%JgQ9ec+T zNKNG6k1vNUy}XGQzvD$+F=5^x#pa^7$G3mgWJ4>xtqv8DEJns}{|ZXA)TJccw;f2e zU#%~PI=^AREQ{S!)!Of5h&%fwJGTbk@DN+3yCOXaV#Em~q_#%rk?hFu1Cj9qwp}7G z)$j&O&9c?%n#~l9{`EIgaIOKiSBchKMNW-M104LLQqU;o@3fdFuRPSe^_C4L`ppJ> zpzD~0bxa+yt&p`w2UXb~JGv`DT2wpWSPTt!YnOMpWJvfiGu%~ITH`N7B{>WUzX5dG%JB6^MmEb^6!EAmxvgd*Q5^swGuf+<1?zOGj+ zCY>|t)CH4>MwCUC7O9OWa;$YDNSQ8|v+2@Tuj#m$Ovh(KN}jH=JRK_fSAZ13Q9_F3 z8en^sXw6mR6r=<=L_mrl)W0Y5Su&abjF2Mgia?4G{pOHjMdG)oE-X+{@4|B&>ZL*u z`}HNjB2?k)fZ1Y^W-b^|lKP+}OXlM&v7m*`*xU$LvPH38mA-1F>qWlI&c>DLa+Q?T zP|?2vt_Y42S0vW}+p9!tt|F&!CBPv9R|KK{JznRN+3aV;6;W3NSA^&{#}$1AhB5VN zAqsyHoE=>^5J=d&OHf2q+}quX`LsxY{H`oCex%tfo38+V@cG>vLC7R$Ki)d==WGbc z_%l@WuK*!}qk<6rTm~VLqBU2MQxFp15Cb9n(ZBV6z@H65L|rim;m>z~5Z-kFiimeM zkcfB0x(axy(8GRx5vcIT*8#^<_T$zlv;u^%O6KfGL5o<%V&p^b>X_KXqE`9%f*M~w zG+qj`*2{{T?ZX2H2(is#yW3T*zaTd+vgg#;AZHb%*RcHs=sZZBW}Z6DoI2@+BMyOXaG)>iJ|4(-Gn|AN{?t+!}eQb+ID6WP^X16^Y)`_$}P$EK;5GG3y&BSCGD0o&7& zeKU#6>?1Exv(V=erLov#J*J+o$aJ^ z5O=m#&ONR>$Sv$~4x1cq(-!kVzQY^ilA$83%D#%%x7pN$0;=+hqWB1jwD3KJ#U2ifBbZYrA>yc0gb{lR~|O~mcmGO zY7?W6o!Uke$xdxt^0AX!2qL+uEek$wYS}Q7om!~$vExe!k-XG$g`bz0HjHJ*pPt=0 z0dS44q(BD`EplcBjbdfQy?N9L96s9P|0QI#++6&ja?#S& zMT~IF{gO-x;oMyOp>mPJjqpLN|J>am4=T{j#UCnHjEwPWjEOK86YDC0k*tkIo|Sw5dRJCnmZ_i#XvLc)N+Bz+(vO*;4T6t0;1$6>}vNjo7oF;U3 zVNHtptSEgtT2$p4*_HFla#hXOV~6o3LwW05`kcI;d z?FJIFMS;EdfFz4yhcQaIwPCY;?hOHo4H+ICX6k2ttd|iHX|Zt!e-J@F4z|xvgBRN) zfI^$0S>4c4GM^deFA(`%#bU6g`Y#PRr9%E*0IrMcC2zd!L)NM zSzG+Yd%S#~Qnes%NsSz92Wg&T?JBCJqldq%3mur$$6|Sq)!uLGT4>)Mf2eE^%c|=< zm6_Xq#WV3hs#YE(&g_w`xI6tFkGLGg*}7T6q~d055(&FDu&w6T#5gp}AYD4pAK+{q zHYHdRKb8w-=Tf@20R-5%MTVdTmE9`EZ#cJ^ zFY-!c%}^-mZoCQM^*3wih2e9yYWS5>7a^Uz)<%k3Y>f#lil4FPh13!XwsUw-;Q7q^vS?^;GLx!TFqf#)>nz*Zf#Q8p5xZf!oC9Hv+rzXF$ZQZ# zvTg-JtsU)>4Stbvwo1~2>i*4@LuiDLGhpuWj3nXU#hP=_A?10+msR(c^&Hg=lt%cc z980L>T_@DoHgTo+IN*QoiyhMi>rQ48|9h|Q@dtOnBCLdQB8)_Wcb*onGq6b4X(mWn zUkx@z%qQf|YKSZWN&W%n2&pVM{BUVhf-)mxH128_uTmfp-~m=yej&ChQLk_ zVVd#wD`E)g=f;E#a8#CLT$ntw7diC^)bH&2ySz2w26?K`u*&4*TVJ(c)N zlhAiY%;@@rYvDf@Ya=n8_PjIJQL2H0LDT5}aS6mz_0~=8z7VrGW zX(<4}zD3_Euvo>=Vt zX(pj4fFk!un^^6{fYNIi8s-3ngCYFo>p%!#57PnTe|axnN_0Rn{`6A)2PF5mlZi!US22 zkd`it{}r(5LuWCo4bO!8wE+12w@~8^B>CTq-=p77mAw9;|AJ)x9o|X*nOGOk+qyH3 zxBpVrpDPA)gMX_|)!X5qe=!{VL%S{N;o#8uG+nvvb`3r};|cQN*>#F5YNy))cg1q4 z#`Ly{F}-hM3_DEcXLa&3m4apv3AkQxddsyS=PIw>P@wPNXU;TuB?JZ4;Yp8r!#OX< z*y3y4MLkJ^weHKdD?N-;i>#KqY+X1O2!By_kinRHC1(m4C;<%j5_hbZJl?v2O&#`L z=n&L^PF3|oo!CW|plVlrfy2yew!41-!rWIRVBMpo#`B2ya|V&m`k3HUClG1TwH;kl z-O)w$9Yt1{3r~E741*7jO|+{!PTYRUOQJX5Ba`q@QgUmnolDJcSt|%|1T~%-BPcjj zAZD}TM@Q#u<(NY!-90Ta^d$0O3_4^XY7svH$9`km4DmD}4Vi=54|;~Y#*T36WdB5- zXmdJ4>YwR2gO)$%)577H{P&By+Uxd|-i&940o&aNJ2x@4E&cTZ%vS%~-qH0qj@zDR ze}#eKaGl#E=fwHk0Tu=N(uY3wt>}Z3cy`=o;vmV~?%rbmd#x|)i=?DD!F9Id0d{9> zilQh=6eW^kv0d_*gY?@^+5+VU??9Em#ug~YsBWefSOaK#k=FDoPHutH7$OqPih}z8 zn_M@2o&8VVR_M}aPWsIf%+iwz6>BuU9|R!sMR@ADS`GZURSobo=IH?A6QBIyPeMh2 z-$v9obsPnLy(D3;5UrRSr7vm)Cj>z3+&2xVhY^p~V!zQhddg6RE}8{DpPI3s2g2^A z&2HN2cF&K$c*`ba=Frup6yZ;Fk?-%`!K{66{2thgvKC^tpRnA5bk^79`qb=R&PG7E z%y=YJwA?2~_vP#j!M-M#5-b{E>Q%k=yfrMVO3~HwnYMIpy2%rZbycW5S>yIR4OZnsGYWn7=XaPc`E; z`$@L?MFzU|moa~?VD)o^%IcR`1894Z*7Pb)S^WVFG1tn>*w4eYOmj{TWSR>CA=4ZZ zC+;mW@ZWp8xvsZj(#{oHvshLH>PLYLSC_NhH7XYitnUifVZK zc>v0sv)ek# zQta!myBoEgdX-0hjrfqY~_q5Q$Q^a0zr z7AL!&{Nm#(T!cT-MW9}Aj*zc^#+z5{=K(nq$*1fm+1e9V9}ZOcD_DC1qqO!U)&SaG zq&2;YQ`TMpLxi;_3L5|a&t4)b+6owwg7ll6@zNs+UAm*EnIMQ*qmVG87#MYqNkUz6 z+9{Zf4sHGfc@^JEP8eE|z8CpemD|nn<#}zZf~BDfwAWeQMY#A$YcD(a>>dB*G=dw^ z$*J^1s?CmoaI5>+8H+X#bJrKB)9w}qv%?@W;ZU~R=WbfYIjM*>%5o3n<${|8d~f80 zozdPs7#l~IcrnaHcfJG)`Mk#D4TTjuFyM#Np%h(gd0x8l1W@WvCJU)ldSdUT-64!tRDMQ~;eq!O_ z5p+jwBf9nZDHR71Kpi^)Ir1D=%sqnLk9mtGz%V;|-yjUr@$|;&EJYimP*R{5rnM9( zO)#5(!%fAqsYx4_&wTQ>V)4O)=cqhj{?>!#7l@#9w)eT~5$*cUqXVR)5pv@!hL9X* zBq$~sKlTlxD07IBML}X*{C~Jl)Zh@m(JM+M#Z6yPpafFJ_ISK0qFzLcdJ!k;MVzP? zQKDXiMZE}h4<+d~7b!>_WvFj196v?m_$lJYPZ2+Uiiq)3#El=QgDegOx&_oB6C>^f zx#k?{Ji2Sa%5pIWpjWWBxT+&)fWpcb-XhSJUWZfrMTtLqrVntDc!>izK*(yVjuscI zqr*1Tyten!`LYGGz8+B13y}3|2WT6OvP_KX*ze{b#{^^NyL;v>VX{)aaqV4uDaHT~ z$LhDbc{$m|jkmDLY+&$BE%&X{dcdp#zopoTxCAgtpPOyD8!`xXx{5`Xt9W7C8Bt6^ zWWf0}f1q{(AsR-HGc9#5zs4GL8zY<(4J=T_#Zrk#U`)8UMrgI6dH} z!T^MlRu#EjZryCZ5|Q`p3Ok)l%Fa2cbfwNLHvFobiFE};+9VUGIlDX?PrJx?G}R2a zPeCeOa|NBSrnuP!58<7CJ4n))f;ACw!2F2-cDqHdKCQPs7oi9)Z!K!VVYeLPr!up{ z7X*#W`GsJVx^Rpa7Z+W=H~;tsoC&eQ=cd`6>jM#C<|V)J11f==9qp7wqv?aQ8o|~R z;?$Za0jzf%*h&Z}$-QumqDreIF4k(_>>#03I;&8XOMOYlw@#}h?gps!@d7fyf@krB;Ye0x&oP{C0}(*e-JstJ+8D+$xW zP(_iFD`LQrhY^$3Jpx&f9EX%cb7+1GNAVIy;MkscfouIIi@Cc1I(%_QF+&a{^;2o) zQjIF^4-sQjP3~`NIl+d~3`_7dAuOeEA^s#4x|Xe!W+zFh>y(`}#>TlLoQ7_*27nJJ z#(;;?2V@AKb&Cr)JlE%41^6#nsTbv-FqazBgrtd5%RwT(U_SxtXU%>HA@1hEET^xn zbfEY{L3w=oP(2^cU$F~s6sTO%0+!y?os~v>MjW^=f|&>WW#E++tW8h$&6{S&W4J8_ z=}rMIdeE-3F;+&t4j+n|NJTLoql#Sa97W_BnBDuzMspRW)M{-fxev&=gUIk^dAe%3 z(15kN!wqwWa9PChAWX8p(QINhMot?Npkt2ZsXB1wwSR|5*!zejocn}_$pJ)#83d4i~arBB7N2UM@eC9y4o}XTx*ZZ=T z_psZ{r~G&IW{r(T?~xeqdhU>bn7sXwmSMxk-Ak)M$yWId@7yxs9M6i`iW?TT34duJ zwA<+)_Dz%SHVpiutPQZGb=p?MO zWe&r(!cb~yP$!1wEA&PobptHbDdw#mRd{;KX zq{>w9#;ZnaB48z6J;3t3-)P(wHeWaT(UV@>qF1YE<@)uJQY!JtOi7Ppb6~KuC{hy< zIuP7y>v;J_dJ5Xqt_I%Z5s)xP#EM;m zoxOUk`l4e8Nc`91xd!jgq&Vr0F@$=fk#1T8^Op|ZtIe)U*wHRV;OMbs#w;KR9Pf%Y z%(_`m+9@;g`nhRixm+n+^cS`;LpFWtBB*~~{)lHJA+_0~hoPeKEq*2(_$M%}79INW z3hf0#zP_P3+2*@td)@q97&kEZFZRFxApk(JD2KEm);bONoWNPH={Y{@_&A6TTeLR0 zwoshXwF1bI-i3;o6Ib+>KX3BS&-WU9>g0GRp4OcXV~10-qaO<6oh-4Ap|h5uB~}~n zaK5L>3U%#3M=W)e7qO&!PopclI)xuREw+hrYTx*4Pw^G;==RezLk)jd{yyQ^D!n-0 zxcB>N*5^`-tUyOGHRu_^=3R?wEmm@%YU1|+h_39;5cEiWb(td~@Y8ESjLu%N6`NSp zZ+Zzz{uHG&fvroJw%fNTP2^8h$q=u6^x*sS@h1hqe_)T4Uu&z&rD_7w`U_E~Pt^qsv@pYwh2E&wv89jxuzu zEg7bLK@?(&58h-YOfU46S;SVAR&ai1iMIgqSg!B@*x=1Kr+ces5oqOouHDx(Ha!wq z<)w`_&*5dg-_PWgV!y*Qzu`g%Z(a8D?esUuDhHP~vX6&N$H{CUcZx{Rg0?sHehBcS z7!g((5EN|dND3!a<&NI&o+VqYRp=2=ESBU{?giOp_?JFDElnrG#mp_q_8t}^d3eQ} zrwI!wSQ{x`cxbC=SR5ZZKEg?huH4x2?BkWs6_&7dE}xTTTGkQksA`u$g>%4ARsc5i z3mJOD<;$J`gVSo41$qX}bZ7o*m;MO-R+)eeCy)}U1m`yAk1bCg+8Wtb+mFovkT#5!L$Uy^G0-KRdCF%}RQhGR-0aRq(GhDa1Kl@dtDJQjoOGVWxNd;YD{ zSC%51!O#@L@rh7{=N0G?S|Gm0QHE&rP zk7lj zKRiu5y#}Q!D80e3kG_&IMRWq`A9qqPMig`P>Zk$u{9{buIk2%N6hvNMdJvuEYJ*=hCMX527!>-a5Ytp}iqKau^+-mOJ zYI@uk-z_^yrz=8Glq}zdmm0CZCp@7 zK4sYrck0(Dspt+>AKppsob z7|8Eekm)?4O#yHiOeOZUI%xBoypvHt<>+^U;% zL;SPtuzGGJM8hUb(%M5`olI`GO5O-)J8NUFE0K6~kca$y-V-X(L?m6`NV)>+U@g{P z4ja{1yit|!_I@w+a@uA4)mGG8W2tcC3)4Rc0Tu4uR(>ce^WbrjKmDD1zb!4ev_ItX zNRgS?fvp4X>^i%1a$83ZY5v`DL)fRSG?R_; zv9wx3pv0D{H;1RF%~>hE2x8Z6`h2f157R_fzOY$Fu&Vvup_Y4Y*S4Ote0?k!!gru_ zF{_(aj&}=n+56PDjTx3S$A5o*G`kOK*~J{x7OzwfCi1IA^TIR7=rw|WiY>!96HPP??4v&VoJ=2ER4r4U?8YIA-@>mt%i=hhcdY(fkx@^zhSuf&;0 zI@D$vs_^auJucX|)!wQ`H({NXAIT5L@{eY@xFjppn8!CXZ$(mQ*ob*&+)ZS zt`5qU<{k=0Jm^9Lao51jPCJh4GCW1yjkU}=u5i{gXhqjZKaZ9=pdtKOYl($KgcO7o zH3iU_D|wJ+z7FglGP@lxhtaSc7Z80eHLTeOW~@NJj@~vE%~iD;7%Ys&xuXi}r147j zfooHwW3R0TbItskTtl@T9h`KMN5b)G7t28(r<_X6wRaqh&5-utj ztsKSGUIwzxa}>kj9W*i;uJ9GQEoOIpX2| zI9GVx@;-;E8-Be6Gd_PndcpBwJU`kK7OMBU?hu=Jn-B z=CoiM*6VL_(n1BDP}fMaxpWpk#c0CgO9m)?+QRywf$Fh4j|o$Qfaa~FUB_8{i#%LT2T&fQniAZy-`X2kbeqMjJq-xx zUB7$lMY7GjZR4Dpzf(MAL&F<$lSNYATkn-FPSb91y{{vQY;7onJln2IZy>@{<5*wIK5=!+PRIg!DBnW+B50fbr&teFBSI=M;d$aM*^n{abj1%0~+!6 zpvHX6bK0nW=yjUy5CXXBHRHmXA~>25{hwdiw85r)q=AQ>zb@0<z6G-a%KLMHNc{WP@g1`R&(f*`A)i$-Vy4eX9(zxS~#1W?bdB}v+btOXwklc6HWgc zf3Hd=e?>OF^jH+>Ub<=3b1OhMhUC2z8Wr!6Zj`{ld>5`T1w=2`XpUL+71zurMTh~K zGYm#a^jegkTD_nu;mre=NCH)i5|JNA0PW7LOv$7@j5p^=8mu6bSJs{d75`3qFXn|P zSdSva=v#Hhgi6GGFcBF*r3BG0Qqc@klFZ5S3~+3&87R4^z__LoHr7#pTTVqUK8Pg4 zg2gj7P>zsZ3QVs&-6~a#5-6pLs}8m}v4!Ws$gpRw9T*W*tDFtAimR79gB(!(A&tnmA)Sy79iK#tTGBgBy zPQMg{^rh6Cs9B_XPV?aZZ+7Wz40sR^>)49*XGxsE4*|%I!|P3As^v`4j%BOylKUrjMUPh1^w&2I z1lL@tE;=q1v`$}jXAMwzH<_J#8Tg%0W{HNib42iP zE^%V82_pmos;N}X4lI%8(`~p`BylEHtlEEp6!QKBQf$x>8z)HopznR(TV;Iu^f%h6 zIS3gujl(Tb*P%)g{t)hif7=$m!b5r`NFlYlNPy#Mqn88ULfIB`BigL*$~(O<^mLR9 zZK&uxkoamCiXCpDh`d3bA25`Yc1FY}x+g@#N4hsWr@;Fu()$Y}8yJ01UXY8P9GIPt z3q-0ylu%AdqhbgcDhfpt#Yv+^f2WR`a290s}qw~+iql04wIR#msaJoR~eB>rt9=dy~ zG->6lkA}W&15xY7SD%#Fx%`Hi6B5s8J38cCVCm8IHc&lOs?FI$3EisHv!!+jc$zAb ztA}LjIxa0Nbo)3n{b=#}Xq%Di?FgPf(lrdHA?W*qd7HHIc11& zd$eupNg@qj$o?RePNVGTy#Gv)agdz6QN%zn!RBMa+b(Dz!7cG1oWBtjiEU4LDzPK@hpmgQ0 zb73h#+y}AEHKMy=LBt^^B;LBV8I&1hw#%J?httn;Y(Dx_Mw?{gI%VV?6#^~R;TqCILeq|o%!${%#Z_gwFzUW6_Ur+nk<#MC`+7A;5YJe&AiTHOR&I}!L@xLQV+C)3yqht>RY$k+@*IyA| zCLz$CIB~g2D}LrDsI+D|Xx)H1zu@uZ5C`EbL(&W@!h~X)js&Xq{`0p2J_W%)K8BYH zLVkKG4hST6G>1r;qog@e(7F={$2QcKm85K0= zFcVOgLvS=|VX6E9w~=4sbb!q*Yq+i}M+EWAYkq%wJajM+ z2s3BM3rS-zn2E-uI~X(c6uNdMAu{$Gd-zoK_iZ_*0ReHoG>Szah-^N6wBk4Wqf?F=yZ;;Ct|1 z$5m7oULOoV7vc-VOf6=Q&TekQAH&+PFADA52EQ&tgeJ_e-5*1JHFH1cTxFgatYNXQ zeLRc%qY==-Z?XzQu7I?Qi8_PxhA?MiuK*uAV+KIh3@cmRhbw9n!w)HfM#$|=A^AyD zpr5Uu;v}VuR(+bR&p$^he)e=KtYNY2f#;;XhJ5R(0HrtMmKPjtbnmASV-yD{Z$_8X zLf5{(faw`~C&&}?hDw4EUMB^b*WyK@DCIy${{aTzkxeKu-v-zF(F~yF$+loo7NR?5Q)m{P)6i zDa znyUv)l4)l~lUUlT0yw@U8Fayyu>rcvUDid5oj*=|ny)pVIVT)!z5m=Y%d-s5bPrgX z!4cTR5M8%O>wOhFgtNo+5~Tko6c$7hDN3)x%_T<2e51`8X!gV7owHmyQ<={o5dP-* zbHE22FPDFjc!>EQ#pg}RMtXUAS!s;OW~`(-paJ#MHP_Y0TF&UEj2Z65l6nafrs9l% z_Ttqk&SyID5l$uEl?zi-G&+RIX^1jmuhmWAu#w=aVynU2+j#oMgf!9OTixp4(>Sky zdC&6Ng?nJRW0h+Lry}-zNkkqgoJM+gN;7%)CX*rQ4O%xAv?x4EaA~WMyX9alQ!zSg zK4J<-6h@ElJ2z|GA1A{w%&i^jllsr|qxfZ<+tl;tMaR!NOi`JkxCt`Lwe8Subhkj7 zd+#jZ6K*8$JVInQ_Tvm&XFUS#u8w#lh-$j``uumEmR%b~IP+;nK8_f|kwKhOcVkCp z-QxU^cc~<4Dz7YIB#d)m+UDp%w9AA(jBB7t8WUkh^(Mn$?46R+Q*#J7NW0rug!eu$ z9?Mf&MtNrJ->$%)4-VGm}%AO!r*nL@`A z0A`TJ`03nM4<8e959eNo|K0@4j*Ve;LWZ&D9j36%ACBExHZu6j4`l0tr} zb!!*W-ZiD;t!IK5_nLmCTXLJCkuX<$V_W-{k2&@&@l86+<&|BImrAL z>Wa!&*$)4%a?69=(qY8h8Dv{xwYn8m+1d+o8DJgi$M4jpkp1uGk8ehIlTG$6j724l zi^WigHGcggOze#a#`UODp2A}SsI}QC(}8tsixh)O&d+4;$@@pHr49xeMPx=CYq(Jh zU2ypl6NRBgGc8C5AflHQqQ~hYPR%<$Wxnc9xLP%)>`86Qw3~W=KB!GwsrG9b6K~DC zX^aNl=Qj-_9Ct#3a5EqCFa-n$U6#wjIwxT(i!mrlWIRw^K@-J+&k5tZgAIOQdr1?eLxnH`J z%9`(4tm;cnhYPQg*S#oBx5v%W!u6b_vzM5tro_1IuSPJDkKrk7Va!nWuHWxeW?McB zyJ16VLWl^Da;`NMKqfHEvZvwtb&RWcfxoC2-cVSs**Z4g62jL}Rzyk4O;Ya@P4dAWqSdd zIL?B;uoYo*41ZDh_60BjN+ba80`z%31C(GeL{k8%NiH7K$yNf@OtmGV4r?UY_f_V} zx+q(sj1+mPlMC&*`#Q=+e0X{Th1HG{>!}NGD1ayk75anLqNh`FwY#pMpmiB!wHk_&lSHGqk2auh( z*P&7m#blD2yE=s7x2B$pU`JDj$2Y&Pk2~;^oiUTNKH$YdHOdXG)jf$zer_M zJc7@SAT4~ z>r_)VemS$&*`lmRI7pS6spoxsjZbIvhkc4|KG@y#cV19$H2sbj--hT<>qFxAlhkqC zIRqT-|8BE;d{-t9FE0o)}oMUOg-UjYP)SNa=?N>#!U-9G{JjF03}^J zwz_T6;p?AF747@UpR0*Vl2lH(=Hh~28h30WNh%^yDzYQ_;#%80iQLe=$7Wx4WH@Q- zY-em9e2iQLZ))D)vvT6ehfeQA1UA>?t>E@$xjM7?B@Ax9Fuu#!||3oWW;I zOxEUs@O&Oecg&Wr9JqA0!zZ|WKtFuGHv?l)%N8 z%adGMucZr{oFI>LW4qoUq!Wv9VY5N$8bbRpEzXog^Q4Ogxvs3Y#Z$K+616&&cs%DB z=fVG;WY4CUo@3rkzSn&}88W>;o;<(L&Tis=qWAAP zd?{J4vd*6#n)G`8+yUHYe9ladb4{UsE-Otv>!*fS)py;|70SoHW>(*w6yI3$p~~wS zGb-ePqNYL2%}YXqI!cC@t!3(N+m13J>~@y94rqgFwC?4$WRm0Z;N?gAPe9Lq3lJ{T z!4YVJrC34WA(2yU$*;_1sHRi^s%E_aHJ3l&teNC{!mS{a?n`MmP4Pn)*rlBW36>e^ z&5lkZ1!Im1b;D$FEe``OVgk@u#c!#7B7tX*06Z0!cns{HaMFCL;Mmtuz~Qzzym#<_ z6XYpt6h77$m7UZHT~5Cw`)3YrEUmOZ=!LSIC27~GB!;3T;c!CC;i#2-NC`|EsKOmv zJx3cbgd3O+tvm5{AmmBj1giZBoF)lntyr-FvNnU%<~2pp7FrY1C^UVR@h4T=#fcy$ z?ZT{@l75b8mB*0qF*gmo_@f99LB+$wYzZs~uUc=k1Qr;fSj2X!_WU$qfeTZc{LX*$@R; zh#m@#$EnhrDu)tQ_76gYxd`IrG?1>!vbvlw?%c-P_k;x{fI6Z+#xqFWRvU4)KV-2^1V5s(m_yyo*0!_p(Wt=5wR zoU>|EizkI2H@7vhH7v&Asu>FT7{MBvtpX3xlM3`3XLjBpk1b_X1x}) zsaGRUHhkBL(4AxJmNn&Y_6Y2rRXw`;c~62ac_j=&MDiJsTmax*xXPHtm4C#fQq~R7 z+@Z7sh2}D7-$MgYWhX#d%j#1VR69rVXTAS-H-`cgznfJ%8uuPgf|`;45@2qJD%vA& zWfwwA8LX3diyi&uNs|)YP0F-X8wVgaCI33 z96Omw`>OG2Az|i))@AcdB^&@ZOXYxVUu{ zanbACs_rw`0z4`R3QHjBqZhK)(it_y zvR7%xb5Isq=bk5bc2)ghTCrv@wi`OIZ?$@H8t_WcTD+qp?)e^(<{RLfk zs8$zONw)o|o3xc*0Irmloi&$U2crP~j-H&obTLI!(@sDEDIDw2Y%|jJ+768wL81z0 z<%=*NbR!Ne9p|t5G=EMWnL#bF=5qYh^KBggJ_W*X^-XJD)iX{{Ja;dm?PmTByFMe zn$NgofM)Fhf%zuGa;C`YnmKUBUAot1@RCK#A9yyjwKK)<*T1J3hw{2hbrnQ>0qUut>-Hj1& zJpdhkUrJX>$pslRfVZsFMz6(jclm(bE>59FvaNjRELC*|{d-JLD9~lp z%7!iy=Jk7kzX`{<3%|!)=YzREZk%$zl|f>W!*dz;?@vqXyot zRq#Xu^JkvvrM5}JVtt~o;qVXP*|Wi8IUa`CFTza9bF4j=E(ttDPRbCN_&frfx;Rmu z?_25oheEe6k_nzz=|v*p@LWeo^aU0TKB>Zk2=PTF*Tw4FXJLj|?-l&=quKLu?(d;K z=zecRfHn_O_SdGFM_J7B2a5$1BKc3LA5ymi53cXGhMV3tdE@cJVVRya=Xt?fY@y$L znI9_r=wK+cOF&SUW&ug~j9L%yuYTIk&cKoeF@LZ|dY@>RL9=F%IUs;^n+e8rW_bQV zc_Byjgp0#Y4p)wLXEr${jNOwXIp(K}u63;GcA%r=H|B;s)%AEy0xx<17@~JLeRX`x zjyJvff)F(R^ph3dY3Iv^H=bUf^EH~()XwQY=Rzj7XM+rHBUnx|B#iFqeWcY}2U{h@ zxKVkdNGDK%#CePgpi%8E@#N0(B57yJ9D}@sW=FXJBaufIdx{MFuZdB7;jdL<6rjNa zU6Rint(ICR^K-C`Rq(QFc1@H8HJ38{IIzXMA!-X?8c$Iy)b-FH+woF?h*WE@(qa_1 zqGhyKSDlU10{P#wgOdu!M!fk-Ov-CANz|RSh6BG!;C}E1aM|WKARA+~LP}h8gFRm! z@DtaT6fJ^Pt-1DLMFdAjYhVTs`}YePyrE`ehwL(2s7-Y}84z`}9A~J2`xUr$O_O%N zUBBMQ#(>>nHA2K2P0!rkfzhsGeLloo?m8|WuE9MCRAC@h6Znd2pz?~|Z0dR+DAbvI za>Y^&5F%lLU1e5TyizyKQLBv$>#4b%#3JM@=Y#kZZpBNjgk7rrw&N$@x2`zhsEinA zGX?cW42n<1`P;zq4uUu9;Z2i9tF^=ciR4N+zZPq8WjB|YCCPrU#3H(CnwVmBLi{|V z#`LZf3q^DcZ{Gqq@x7%vF0#~#^NtF_)VF~I!teOZm&~CNPnwp`)PqF1UsgDL7W$DE zRsAH~%M^jMrcX=an&9T(Vs}Fe-L(UqSblC*DdPEj>2lokI86Alin|zswR~sNrG5gF0ECHClV<2umfQ5|0oE{ygexus z0}wK%q&sf}YGe)9Fh%aW3eq_`)cQJ@?+0#pYoV5{fS96@&7Y2|Iz3{OHTf?1Oz3*X zW3;?$S|d~w%v&@Qjo?*;qz#)yO!Mz_9?mQH@l6aTu3eeuB%O;DMU)J8_;wv0cc5e% z?d?FmJlLtD z2{WpdaA~kONmP0-p;~|7`S&QyZy2;JDve%s@Ty3zfBK}5-Ey-*-mA7`A}#R-ul*tk zZ`Ud{MWO=64Kzc>I5m0_UdnS5=|b^iizh#`qKhY~;YaMjD*7p=qyUBoQUUX5fxn5P zA~oF$1AcqNtt~oqc6NbUNzgIuWD}aiu1LyA(vUJ(n6I_Ud)}#@KvJD#z6MR|CFpqH z1+CW^(y_HyqR?Iy)?5^25-|?lc{5A*>yp3z!8Z0KjCTs!BNCMKWTOe)NST+D!=mVz z+q%T4gYw>Ws~#-Uen32{Esrjnjh?!nHXNIbr{ffAWtCP%EEl4{w99>-wNx>5Q)>Qb zrs;Y%1kox#THu*QyH%Tf8OJlW%*8lDENCJczR*DfZXUNWWQ4by%e+jl9{x<$M^f zVCj*C?m(@)`Pdh}dIl}hqNPt`rhsU?fKV%Ybdn`j9P1ISS}iF_&B_v{ojSd|M#Q8k zqyM;Bix6b`)`SfpA@+kzu

    E!`9;`Rivh>lYTgMP*^wOh8BDBo4MI)rrv53)5(MD9VyrpC$ zt}`M1LP|ue8B<5E8C7WRD`v%mDfZDA6Q9HU|CxJ6| z@Hx`D3TCX)!W}(zfaaU?MKZvS*^KMG9=2WD5k3^vQEOZeFf6$o3kwFgzpBwZPK8~T zSG4@={=tNuYwkJ8$Mb_fNqYW?jP;oIjE+oQnaCSSC>Fk2rA?&u91n&I-15clI$cV) zC)U-y2wm-7c*RrGu++DNE#al2t#1f>z)Qr`Ut7|=asEgUD zD>)O3J8U?lY>9N8$NH=hYvhe-{D?QK77%3n)bjBQzXR8dB^JdebEuJ8u6T7aA<3T1 zpnE_vHSfv}>Ea!uJTGpsEwW^YD>r1l?xw6b3dDihZn`EbWFw(Ovcx9_PgS2m@99nt zMZecl34f!L{Jc}z3h#)Ih%QK=iLz3nx1n8fV(86WuqV?xTSaM`^wDW*uGthZKVVu+ zsaT&NlBx-*^$){NwiL6GXo zXqL#StMg)NQ*OTlBrgzn-;xXbYN@V7xe(bqqn@g%}r>* zn@zejRwa+`^vyWAlEDp)vcFPv`l!-DdDU4bg2Ello>4y1`9(tX((zSS(S&1w2L<2in( zZGNht&_=%dlp)2F-bLGaQ{|R=K;R;YLp9PzoFfzA5Yf^p_SShpzB`|jQb0sUrz8eg z?q@N5->DQ@_AxI~a%hj*BHpY%t#2M%6j1R}BL|Ru(p{{}853X4q-K=?fn>D^ka##- zf}ra$@e$Z&=iwK;WzkZXowb3L2H-*?TXwtZS0(6+^16Mk@W0d^cFR9!u6gJRO|-|+ z)+fuBri_PCMM4O;X4QheC$aa;CO6O5;Wx}(pBN2jmkNZNBE^w6LE2y!q1ys6J)0JI z9zwf~G?!0k;v7YwJC-U=#^5nQ42<8$?lcXi{w^(|ZEK!SN(9<+)Lh|pnAeVN#$n;|so1+WF1WX7EiUdGX^MhX3EzKl~SUOO=sIPoX9p8CXoYZGdGGfaP z+HKQw=DT zSrlU1<*E*xBL%=)3wCunQk)Tk8yE!h*KU9kto6xpqv@j|UW*iKh4D<{ehV?PRX$s3 zBTmXgL^jGp^dKgCb(PbS%s}T!V6+)H%7MdTqG2e0_fBa?gPKR}3%aU%83j!gYQGsaSz#S= z*eVSiLK_iBem2hNkTzJAwqI~gDI~k*+9E@k796cakx@cS*@mTX94=ZdP68RQW(qYM zyfCK8)w!6!V~x~n^6yJ#p~^HQGB}oD3V_N)HUiB+PAlu{RiKEO z+y<}m`**Dj))_X_LJ7RoH5LXa-gTr+oxYvTk6**L!9HO=MOiTkk$>66l>ha(b4$EE zY}H32wy@R?=l8)Ix~m5?>_5$yC@rK zhqV6aJfT8u)745O#5V_G6**1Bi5oOw^~3S?FTiik#1Cv4G@`RICn<0k7$;YfLG$su z@OUo{&KOasLp-jOdYYmT`BLQt%%(wP3@AY&UIaE93Z`vkjml%?euGJczYx23ZRc$4 zW5k&xk}yI}KTA8G0i>B$fPjB$!k0-H7pbq!p%dvT`p{iYfw|3E2ytZIHLSYO|Bl)Q zpP+g%K^IV7z%SkBTK2q9%K?PABCOWk}Q8>DDjO2M{eu3*+)UAxj$FP{*1)JxfK=C`ED zKivRVRhR>;!$8N`B_Wsa-EMgH;#%k_?AAA8PLmQpjgx7?;WnM^f#q3EUZg;Aiu)1K zMEy-rfM}{#kk_53Q0`7lqDcC>@5hq|bm+^9;ifA15DZhPH6~%z$QWHPm*OrN*Jf*G z7r0I_){GjbT06W6%e%Q0&18Jhky2^w`oi$XD`#XnFWF3g6Z`#q0q@$=eA|j$01?!S z+`NG*ZsO@C^yzS9tH4O_faIg0j@E*)q3Uu31IQYC>cZ~Qzds_=%;b+{(MW>iE1&*K z#4;_Ov6RE2nl)WQ>LQqR(U|D)zaqXVm5B1Zj4A?4_(saCf*P@178NVijj|9S@Z?o@ zpmfXBOLPSy+>QvdyVnj=E_(d3Vtz1e9JVy7U{~m|=culK0GB~928VVYhc(Yg6Paw% z8pSx>=lhl-e-EfkXOIqAZ+H}v?7@~E$Gn;X;GiV8J!w1`oCJ+~NNZI8VvjzP7SX@r zB2#e*Vh7eqF!M0=gx+X)dkyqOm#ABO0n2FkK*MI1{QE$JrzH6?el1MM4Yg{!oYM1s znd=3VfnlYTrU;yiO=ARpI%j$`R`*%8lS9PCNqL*%N_DqO+{ejt6i)p0@*mIMSv)6; zqOk$mC7%f1&bKiLAkJMH-bk{!c{JXqG|HS{Fy4mv?<9x(m??NcF-uG?TGEA63}vE;u@+s;fXa(hf=*3_U|ziz2SbV4(ZR zV%^?I!As6mw;zd_YW7QdTX(=|xos0dE@5Q@M-4iOqH|*8HOERMqhKf@OWJ=rg~kt| zdM+IgvjeBp=@3~?J1Z^$ggqfmY4@~n4sr3EVm3; zTJ6zH!;DROot6u`8U^!QQDj*4vG*)h#-3?8IA5^pBc1E#b}wP`ptPY0jr}3pdox$j zv(M+a+OC4xOASWEJ_zC^MQSM>Y+Xin#_8LV5nL}FJdWE(H{#Qc7Vc=KsAt1DeLPuoKD(Eec9BUkt8Gm z_VY5XqY%jnbesB<3i5>!E<#`s7-L8f5Fkh;XctSsJryz50w4A#w`h^gQr*4z`o0J` z7{3w%-+OIb92(&xtm5NyknmeF3}MG_DA57R^Sw`+=(%K0q?oH)j1N;Gf^gM?5EbwWs;fR;wisGDxU` z4ehU2F~|_XJ}m3971Q886+dC}DQ{V~C1M(04!FJr-XR>h6qgg5`6drvxsnW!_4`P& ziDbvU9397V+FNwAVICMQs0y=2k(a90e;Ri23g0C7|fm_kEx=vykA z=j$w4kY>aZEl=zs1p_Dj{3kv;LULQTfyl?9q6g!<&jA>8k$OdSoNKRM&r$uOE*e62 zN*7@k^zee=Vhjnb;1?U{G#P7F8*wFE z|Bi)`@RCT6OcdS<0#oq@BrY5;-*Q2-!oq#ODtwuCF}V&U(DuJ5JEtH~f^-{yXp7|>nwM1iGloDiO|616eWIEGB< zIq=Wx}Et}tv*a)vOtAG`nX(i)ht5wH9S#OREZdXoR^Tb#ges# z_`^>qxY#%_ZE9F0d=kwEU-HziiKUWj&&mip$J6MV=CM6|Fh?mQNkhdYKRK3^MQL+TJA2PSakS6lqbv1)?0& z9!t<&8x(I*HR;NVQXXFQZ^xNHy1Dmuf;}xx5q~JN@PcENf9i|9XR>|Qegzh-)oO1s`Do%X?^e=@zmGM@}U})@KxF1 z&})d1EUA9v94D6zrJHpn3bYc-AP6(P22UyfgGLi5Sfi&z3~iaj_Lhn$pYQ5C-=l;C ziI_~4EHg&DQ6K3>(KUR)a^}b^nrxCsM6NU`krc}$ONIGZ8a_fOVZu3d zXbhDa-20S_1`6|F0zH=+1@l1JD7PjzHis`9)(L`m9fBZpVX#1u2sm8RDdL@=XNKgu z&#P1M@BIW`dC{S@8n$?vw)e_G!fDX=>^$*)RKC2qOzDR$NTioyT~_7#s*k*B;D^s; z-thLIG769_R=jG~wCiDeyn`^mdqA^xQhiy|ypKw&rFy)*Ml0l4huN#rnYips#(jPR zq+-Vm?6FmTb;5U9W$6^&j(He~79*U+~HYDHJpo~`0(?Y}iM zEZtnlm#)uYc5#~w-0CNA@7ZR#fRMX_mm57wH!}ofjVsN$Z;z=`svfQr?UOvC9u6`z zh$+W43d=ypV5_8A5f~Y)fZATF+Ce8L542NKhhGgnV(2+qN7>%+@`~7we}`TMvkblk zK)E%%sTvzY%b7Fij#{)5V2srQr0rr@oqqk#FR#tlQEknlLZb)u9oY+)So9>nX`O*f zk$@UsG*I*f5q_5@ff33h%iwy$L9M2|ocTHI&m#IJU`|~MdavNbCn{1|zqXAm{w&zs zZ!4Xd=lG5sbL?6?t%v@LbJtX^x($s%Ixt%5`bc~Jfk-yJ2^9_-5PB&R>GJ=cL3^e-pjhFU8Me`}1CGwq2 zV`?;a!K6hhbyWgO5|XT@1dV{bj%it7$iE13uP3x9ez-kB3=Kbl#d7U49E-npEMm)K zT4&{JfVFor!%tu(3|dij&Yey>ktf$C=R+c$Wmja=@QX4=&BJ%uC%yCPx2G!B~>F*8v=<*YqUgpZP)T0 zdnAY%nfy3MC&ee}ANCDH+Iyd*F+vZzgr?+GajL%MVGAn%}*kLav!8cxt_-gQ>G za;wJKGB4Ut!R~87aVC=SKGc$a+Qeh`>xjl1xNBqk^KLHQj9x zEx1m=@;9#m{y3`6kl!CmWR={v%2ybd$|G0yq1C(C#yU;HK$~x)?}n z99hh6>2zU!;}BD$`WRXP6{>M5-aUu|w8m4X#!-_Jb#lEK6f>?JVZTQu5d?BcJ+TLw zuFV&MYp2dTFwAl{uoDN50d>yukH`RWoIQ#Q>*{^*DFu57jL@=gt+hkVl(|-@ zXPq3X$Z9_uAfW*gGX{oLn?}X0HfFyUd$v|dle96)3n*+6q=1|CpLiNK&1zLdESHHr z_#!z#3|+5#C)vLwsu}M+k=A6o^h^1%X6HCy4#I+);S|*CF=c0$cUz9AUnig+V1xM< zKEz+1lz-|D9(8`6{r<5&P}taE}9kOn4yP zgf}t0)daD(x8FGh*c;~j(7_1UjX3{5*iBovKFAu;VlzMY5X>g8zX;1@hI z8;R%|v;SZdCxmXnPC&sRQ(U~G(^Ep4bJT4z#FS!Ac#L7ua0BR*3>)L!DFO(Y9mVfS z%hh-z$au@Mk+)`k5P6bI0kD`wl-8g#cZz00dThTPgY5!MAhoL1KWEMOIRBm=7u3HC z2nLx45d{$r#qk$KM(MKxXf>4FKYrqF7b~QMQL1(QTT^&|MM|@|r!Ihe*K-ZgBMRB0 zbpS)ltga=UsHMy>gO_Bdl#tIucJ!hF?Gqbf8Nn5UY-E8by8?oW2&j8xhst$|?t&q_ zUdMixG`{>!c5T?OP|L=lwJ6e!`58gSIQUhHv5~i!FihA5qdwJO^|bK{nisg`v_y>4 zfD0ZicFy~2*P?r{cyG-%_lq4f1NPM&OXf|b_UP^kHrIu#v9mC6h?Hhd+2;@ya){F= zU=P;)c4)Kq`lEYre&J%T^uT54Cek2QMNa}aSqBnd_qS_npw!I&@7{|VQXkB_((%QC zHnS!L>#1!-`x6aj=kZq0bZ|z^882kB^P@t07RvP{6`KN83Aa5GAP4+Xlriw5&y-$% zHz5`?%&|E_(y7s01)%_a=S0s??T zEfqm7hcBVwCXlFMumaoEdIf=FbbP`IB23wyHWbI5X?W14%Seml**vUn;-w;4@s#^z z)F!4as+^!3SVHlSz!!I;FVu?GwAl@06UXluXqSAAm5&>^cTUz zS{O|49?HylBVZJ<(uz)22><uJ}$&wt*WQpc5E(hdN zE)gDSAz}oSLN}wH6}FcD=hbZP)^1Or{m(i~?;L@VzD(#b2+!T1#y#NLsBmBIPDS_* z9D=0KVRP2g^`08*-KMaVFBV~UTDx1Y>K6B)CcT@kM{=>RA8?2o6(+}y>3%nI^R|8uzc)mUs0O{C?6-*xtVXK&--X;ZoQ;85Q ziuDpPsyw4Yy$c7go1`CRPd4HK-mbyoaE(Sun01Z3>1-fX#+NWZ+e!N&G-d()2U4=a z!>1m-D5u84HvDD`Gq8xM=FydwmBZjHj5x2 zAG90BZ(IG3kGIlsg~lhYl&Fag>Ej4X0FQjjQ_E>S(ROufg%Wx~<`qZU5C!w3E~u!Z z&$_0~-P+A158(}h>$HfO1Ra*+!>{Z&-8U2-7bP$hnIRo^$p@y}OBiU;G|f4GfZ36t zo#jt39vv4mAU2p|=X*eNIzz0YY%qG~w@8BrHEgt>OIyADd+2UtGb8aoW2Yoor)z6! ztWkJw`fL~}n=4qVA?!SQm?^WTd_a9GF4r3{rZGw%5`)c1L);`}%TE&JfN^9kNaSnWIwip`;I*(lc#1OHat4KsEF7^|SDu9I zd}u$?sMv*h${EYx)n}6fTw96YQx>#l6geK{iqd|3m8xk&C#v}gda;v35VBVz%_WG* zaV?%zsPNpVhJ7@t%jr1GHMxn36`ZN7SzJx-<0{+S7ugJ2g|YNaf5`Kva0(*uAkD@5 zCmSgCgp;8-O#9nZvk>pa=TLPB&!}Bcs(&tUux#J)cZd)-PB=`ah_h}Ii-n!8A%aJ; z0B6ddz{9^pUBB#8?JUgQBrnFD#SvHVBp`Khp=YfOF!-s(I1qLVf8v`1!|}41t6cf- zEjOJr?oY>rh=Syt%i#Kg!+wTWw-$eXB%4<@!ZDHX;zUYpMx;*K3)VzEN5^XEg~yOh z9^1c^c<>2#Ew$v)JPOhL82_SLQk=B-4ob_ONWo3X4hB}QGT!I)Y#XW-w+;iwW8Wv@ zToWbSozcXs!yWKwgRP&UgE7qy6~jQ8uSb^(ZmlA79L71`-M-ZY6uMxDkhC3N(0j7T zv(CcEBZWTDEaA>j=nj|;y^C%}`O)b=LVexqX`kt0=AS{?nSa?w_aMNT`S;X;fPek! z`RH#(IlBLfxz>W24G3o)K z6tWB(c9GP}00-r$#_-AAnrMUjMVUpt`M_XiStv zRl?PnaI;yFB})3eT@mQ_%ug)#+n~w-XZ}7dGVY7vJ-4EK{P6CXsmOC$0U`-Ea z`9xcuJ)li|u|rb%c{UkRC8v4$&qMB~4Wcpv`*9Bw+_Yy;D-ep(aDZ<-NCkt|qCZ-d zEW%(OqdPGh%>J(7!^`pu)+YpW(}goi@911HX%Xn;5YPnx+*LqqxnD_+4KT`U6mmqk zyHNHRb{*&4cArN;7TtJD@c2Bav`@W$b4_gul)7&)^j|?jj0{vW?1N++1Cd1fQCDB^ z8ZGR22qBd$D~u>|ykx9lsfM{u6nNpgAw$j-_~7vRG~%W$@@Y*pd~qMyn1_}Bw|Cru zhhUucmq07b;7j;92Y@oe>5Q_1cj2kAF0VxfQKMp8Fqn<>qSRntr`1K}l^X(Ow8`gm z$7iaC894x<(`z^b_U`sf;yV-!PtIj+bVRud>cn=*Hr z^!Lus2{3Q)H_0~;ikm>@k`dWkaCDpi+=ET-nSWsI?|^xHGU5X>XQDzEVPkKXEwQD@ zk{{I67(S9GIX}IUbVt{yAUc7@M%wbBR5D=gv6zTGZY+b8ENWgk$TapX!z4z!Y=p9- zx6&3wwwUdkCupkztj6a~%n@`iZnac7S`|=+JLk+9YKyW(z;rJhfFHZF2APbG)1%{y zjf4c60eda~sw2V*Cxi`}_P4~j88D>~VagqaRjU$!*+^JacpMx6H#z59xTQqX=4f=6 z!-Y2)&MD+SCV#kS&6@sac9y~;b^mNdxcrm=G5qh;;o-Egdj=f zGB$aImsYOk>q%(RMsiSIKOHI_Rgx^jpzY^1GlRsr(M)NVM5Nnp%mPsSnNZiBTLRM_ zOI0y%vYVExq$%HUbR8+GuETfe5GnW)PYHbKw1}S&BjSG za=*-Wm+7vr?~2`W7gQMN?(y#2iW5<}nSyPbA4p~RR}c(aZG!_%9K4gxkA-Hv1#Jx> z=9&pKCvR{iIGJY$^JE=mIi5|$B&;eOl!=Bve5fY6kpM$Zr8%yYa%6vkB=0GP@skT0 zZE;UP>_FE-gmD(m)8Oc8M;)Ssfq^;PeUgx^CYM=?xRp0-3z)0F3s&Z0yjF2|EgZt~ zdSfn|I^k`BQ~Ee;=(%2Cv2S@C3jHMKoY+v+Cppg^^mMxdV)&<7IM!;;Do{SIYb>{q z6CSK%QfbuW#75zdv^^QEXbn;F%em2pfgji6m!p#I@vzToj!Tc>?OA2N_>#r1o#T-0 zLigfR;~MLO*XV#O&xTuR1jKT~@I@;W(B!VTm=b>q-f;$Aeyfdjc4DQzZu)j@5;S`c z^7#9x+1mDnb0JV0`;aG%CFh9k-`b!?&xbkPk+)EMeS4g=*Ha&G46gtF`Gk@Q?goi< ziMM&J8i81#f8?Xyc`29+FB}`mVr`YMe{BsYa6OsFT#XLsnTj)!##p~86Q=1Ax znS&1OfuMDW*d7FZs$YQ>g(-Bu1#OJ30V?1%O3pH+ZfHG>G-2T$_zlxsLMk}8OPL^$K&g3a-dTP zF$LQN;9GxTUjhn)S~Cg6|A`JULc>P@obYpyUd3nbD@~U8#MK1o8F;iqcHs?ewydaL zYIQ0?qPJK(I@$dVDe)qKDC`X={%P&-kid)K4b5>wKIf@~qOuqt2Ge70Q1|nidy=H(> zLW<}!;_H4T{Y%o>7v0w;+JW~las8X@kHscKZl^ojO&!1j58F`R$x)%olcVqZg7*ht zR73A0)5||yEY`$;7|Og)g|o!0zSvh~Uh1(ni+3^LxseCxxa*-dBqh~>AT+DuhStq~ z2w@bJk2#S6jSy2A7Z&tJRs3|aqMkr;*5Ri`(||KPY1>Fy$mhR` zww*s*UFbnv>+ku1ohC?ijyq&8)iciyUfJ!Ljgl=G8_$jV9>&SA>J1K2+o@`@wT?wY z2rzlApaDpul*mKKzP-iizgmmsx2B1{pX-&``2o(gvn`PgWdT}$Pr{3fc8YUCA5kPn zAv)KGyCj!s48lX9lfJL=;{hGQr9~BX>Hv-lxM~v%ZIsNnk%H`1AT4v_Y6ZK#ao_;Q zof8WoHElO@S0BA$9U-gfShF@x`G^PRY61m5X*cK%*<3`)tdn?~f=jRG8N7aq= z;59V<a1#2qi4xk z#+Ll(*!~0q_Aqag;r^;P7SGUaz{J9l{Xzea<_7goT>}8nZu%Aa?}z`>q5QiWI60X( z(;M2^IXgK!8raiY*qG7(k4jglST9r*=`Soq2ml~S1OUMFzl<=m_OLg%FtW3CqBS?L zHnp~}HFKhMGq-Ryp|iI&v+)F#$I)qgIY1DK)9)vApUVpXfrmu$Mt5TaaeLjv+u8<- z?DVn^4c?>c-#*TLo%ZYXvRmeLxlopyU6gaA}GLZC1kp~Ju z*z?a0hykezPgJobKscxhteO}tEhV4pJv=!%sfDeAhlfW)L-V`tJ){R?h>4BG$H%9q zrw^F?{QUfV3t(ht2Vcw1&OSXo_2cz-aB+Fgy{o98^2cOYSy`EwocuMsxw&a+Z3Ud^ ztqTeQ*2l%g1yu!rApzp?V{C10t*oq^pP!HYjrrGxhD5x)y!trV*ueH?XJ#@oG8!5h zy1Kgq*2>E%fq{Yj(cnV$^z`UyXaHaUmUH?2{Ga!C8Tt5pJw2gVfB;@zUH}SPT3Sj= z&77Pb@9ypn4uJXu^5u<;jPe}zRwgE({)J@%#{ppU0RVx6g9p&~`udWSlh4e|0O&h7 zAkH<`*4h~w8v6O+`_t0W0_xb=*Z_)_6cv4ay))C(!&5+x0Sy5Ke1CrnMD%6==;wu; zoS5bnou6CeaTA~sfINY~_#;qMb##2($^v!+m;h4(I12oYj)vVsDg%_~prnKZ0C4XE z9s^zaa?6bQ#RY(jLzhP~2UI5}A_8#qhm`<90V4o30oaI&g3*Tt5Ynf2b#?Xs06ZP; zCFbYHKl`qQNK8x=X!eJ#5)~B%fC-zJnE`7-8iV+^ruJ3$M*H{g?e7~9fbRW!Mc}UX zZf@ulNOu4l{#gF@dF%Q4`MrSvgaRGCq~AV&P0h>zzjk*5dNwvT0I&%FuX<+}nybI~ z9kVv5$0>s(1e6NH*2rreVwjwB^Xt&@UJ~h=ydY%VRYN1|%8(aW%oKHtD>GSkHr>e*{!v)PmCrEEKC* zd2v|-JY>+LGoq{W*gb%f%T8WjJ^Me<@V0)muW%Fv$M{i)dgULPn6M}3DydKW66Ezg z>dy<&uR{P7#!P&gFSq)iY~tw=Cdz&Anxrc>R7Eop#w4$-=B_Kc5X>Y<__?ca*YSi9 z;K@*y7(D1-Jx@51!T4)gjgMJW_q5(FvEg9(4TsCo7aRer@$X5M2U2+Gfm{R#pj0U# z6;RExzncVVSGy(OZNOl{)VIP4IGPG}1s({-Pb`!nd3EySEvo*y@C%dl0 zBsZRpwJ#64ydrcSyS_WGl{@1zi(62eMX4G`RFy`VQW1ZzbFZV1+bMTP z2_w~DMRhJ)Q;b(ryH?OJrBWYevuNx^CeT9(B5Q*`F^9fC3s`i~#ny_zk#1WPkuasD zI~H3YXc$1<8vLw_J2e|c6fEl`5%k{0qHHz(ts@3ZoG3~Q>RO#w1~*ps(rZWK=F?@7 zBbmpql}H1+ak}@X$j(4mT5PLTCv#zNv!UN!VnIg3pbX!(&>lcaJhQ_!8<%Z?Q%Ya_ zlK8zSHnbGo_@*r@BrhvPM$}2S_!E*-!Yqf8grMnvG?MuVzP-cBbyDb3MP`SFr{)@myWL ziN)Pl;?8v+2}u_S?iF@!asLyQvz^0aEpHU6&2N$ugOIPNqfUPBtXlvgbR*_jX&V2i zi4SV!&>BCf-EB4GGS);$WMj$8_0CH9jKm1`O5EV=!v4!aOmVeT7lPE!NZIxr-0ce4 zg5GF%5$0oQHLmjG}FKMMOh{hWn0=gO%(=dh6igc!mSHJSm{JSf>uEtSM={cVs1T+hTio@=$!C2_x ziZqGoQC7AL^*r?P^@NdzQK>EqS?kW*?E{@63bL%Wq1|rFn%Wo7loDNd+#*#LWg;wh zlfRzTGhxhLG`#a>#1XMmG56m}9_GEy>?X5AgGNf8+rx^c*7>J-c_w^>VzONej;y zHUdlIr^R>YF!9}IHT8?H+4-@sc+BTgoii!jz*hp~A=2rs?6{NnRcd>B#bO!xj4@q# zJ13%6E^0#}$>fhg25J}DT3>0;urzz#d%)vE#gNdJWeJ0&Zi)> z6Jb`}@p6C?hjk`Eu1keHrOXO$QMCm@P1!$aL1>&|xc5>N#OwGmk zy9x~P0{m1gF>3CA(mFXqnk-EZCfQ@^3ww_!>#A3`k>_&$u66#crlfgxmlWyz5bF<3=gZ)v8_Jd5e zRMwd<9>v?VL?bru4q8v*W2x6gIlmyl22~ew5^fK80rbU*K)ztQNu){uvtWUw_$4(>ErT z^X6;X^nCkH1if(}^9F;c?hi7U3@llKr~9PS@=2# zf2Oi^br{^<2>ogN78IZ^F%1LPj~5WBBdXvR>AF{cG6Dlmv(IVdPW_4rZ11LDY~XO_ zqCl3i>K_3VjlAUto4PCXv(#L_}-Vu4g(Nzxj`vA4w%Wdm{)N~!ad z*%GP34MBeMcLB|{QTHM%FMI}lAyx8!#uB4E>IzzEml4nl2cdP(hsPrk_CAzwM`+!v z!rHKWr4&Hhyplr}d$s5cxwdN0Es#3|k?4%p)05mEH&`?}5b-BsKRx$5RHQlV7Nrjm z+sKX%if@#k=pTifM%wJ5vi35OJc>~W;U4(Dnoygto56Vd8_z)a1P@A_2C_;;(XFvh z1AD!CT)1>+eu$zeAZ6RoKmMhREyI-S0fwuJFbyk~?R%UR`L6K11nM|#w3AeGlh~dp z_=o6`c7dRL&Sv^~yPPqEg8NoOI$TyNG@+}!^OPVOi|y#5EGP}YEzs76Qk&thY1Qno z@>JRr7|*e_&AYbF1%$FeIb(2|uUhP_B^x&XnV^G4aoye8DLK>A z4s8j2A?w$3hKnz=kJYSp$7(}>=GJ)4uw^}#i7fee`!#)X?U{c8HlFEyrvHHAFMAeQ zY0aY3m!q$;TRdkDoK?}qLX!W<=>#Pm0M;n$gdF97u9X=(JCw|paVBIUB3r35*maXI zG5Ujm%;h5}&Eb$v6KKy6%3=cJB<%c9OOylJu;F>f;i@A6BP{Mv*f?WANWuul0g9>Rq| zYSoj?DdzD?@oZ0)w_%XZu>8ux7AX;i&ZsXKUnFLo!+yFMF~Th@V~s~?hQ|S&9*jQb zpXuZzLwKpV;2gYn9M@!0{{W#OoL(zZ3C0YPD)je*gb|+%Mv;dSJE`fJf8L^GTX#Bb zBfM`XQ^YdnnDMd>6Ed(EDtYH>+~^NUPcR(KlC9#lDWz-mqywtsqW#Gmy`ro(_!Y*f zebtt0K4%`%h$ZNOorDLCb5$&-q>wLv_kpWHs)QcHH#e=v(eG&0X7zW=0FwfEOK`F! zIx;ew<>W;ZDazY|q&SP@+lzL({7WiJjG{MIuGFAr4V?-2^rDY`9pw3h(M2ZjHX1~v zGLH9dNy;$TrZLAXy_cHofzdT6jwF6;i#Y6*Rk8SA(6Y-Sn0Mc z7PYwf^jM?1eY5(h_Lu4Jt#15i`OU$`fS{ue+~de{3X0BdEC(R)*my-xSd@k}1)}K6 zzR6fN64_hBO?DP!7}8e?#(xPJtT;)wh&#y#6m-m++2}-P(jnz!!HQM7Mo(M8WXazS zvq)AtQd%a33h!m6D3Za)kKPgdEtwm0kj)|Q#Ke>rVJwS%ru@%ie`Hj!{N+;hE38~- zuq#TqnL`T5$kMz-HBD9U2xj*wwQ2I^hntNCTSR3yY71A)S)*t%F+fxN?UjYyC0Q9mApgT(+)e|AoRUbE4A2M!~}ax)*> zJ|GY7djn2-+4SA7eNXROz%v)Z=XFLHbUQ#RXS2|);33C5Tbh^7$&^pId6=dw!J;|( zkJwP7BT+!_A4worYLLJjyocmzUOEvJ(Vj6-j6m0%+x@p5m1Xcu0&6Ba^^5yhF0KM$ zWspkRY;1&XHjce|9D4PLS zPxd7lUS^-rt!B_QCF};T^?!$n93F)OZMeJq9xKy$c$XaG`-|+9!s(D$CDj*-@eE6^ zBrg$^EfI4rhQ^i@Y_K;a3{-~uY4)AsAlUOyED;G(T9-&rD)U>gAy78!&@`t6KdP7} zJvxFY-N%1TMwT22m|jJfjBgYkLtt~Bk;qP4m9q0*Vefh$ca45`Pw{)|ywUA|&6?_a z1QOY)BXS|V+K!dfYB4|m^mML7^ zE|TMye5}|A)`it#7X<1IRC@Mb z)Y+3v6tv|*TN>0q@0zAnTsusFjetL16q1&tGy>QbwG9eQ2K_ zrjZPTu#I-mpMxerxY<$2QuWVXwj=ve{#Lj#S*1?`S&CVd^!LkYjjW3LRA z8#o;F5F3JSXM3+UO`l5Ol*GKbiFP*-qDq?z0tTE1)mIzgfiCH6R&;=*>Fzt9m48uf zK@PYESxt5H@VTvuuC6;fj$0ghH1i%z0m`KOYpFtByMNpMFdOa^LdgvNj3;r$`nyUVF>Bt^>=B``dfySa;vd3(*eXc|>{QQnU^^YN3ai zJpu;-m-VepEF+RJCq7a)o>C{_Z-bdC72D5=y6G5tKW8Xv#-kljl8H$33S|a;so^U{ zGfS6w0WNqf~hbMed7Bx>tWP0FYyA^RaK2-FoVwg4Jf_H-xy1Y9F; zMdS5YR|n<8{RGXSA$AO=t%BawwN!l&T{L+&BlD(?kG2=fq_VZ#jc*2Lc zZEa+$YtZ)W%ssJN{j_~-8al_#h8r+&FsSd^V7q32Xxeq6jEirU&J242G|l51`_Qzc zCNY(LJ??`M!MsY5`UeO3EK`kRWy#^TmC)T(2|?W4BI&N}`bvWkNG{OnLC0gP@aEfT zr9CH;Pw8#=08DXqxe~f6a_-<>fZ8MAns*~9!96Y`4NIcK-HqoI+{_7K+|zjV@|*y? z2d$e~NG-IL`qfsPQ8N(R3l16*^;X2!aq2g44hf-K<GK9>@A^!-sxNv;yHZJ zIi7^v$0#iJ>J+cetaY^^T_MDHZ@Y^MEvSc_RuQ0ZRTN^H>7RQl^G(PH@AaK<&Qtqn zzE@Zhp*zVJ-5MtSEGxUjx)mMbyp~?fyGo3hz=~y_^Inc^c$R{XPwZ9Fx zm;STjkE;SoG${?fkrtV)Id9<-nq}|g4FpifU4Ras#o@%rCq=Ewi7`0>M7-Eu=&{SoQ4wsv)+@HOzNZf29BX>Q^As?<02he3^1I?s(^l!h-m!) z*QMjT-xbLh@SYe`y>|w!lRGJSt|sq^(6bVg*BkG!%izIMY*4v`M1!A;5?u$5(ekJf zwxNM5f8qj@Wozko*FV0x7a0}m)XNjrIx1poL`&i=;1wls>VI!T`!2i~w~F7%cN_wO z6i)uO&msf=6#<9P+K^M>20auOV~r4^aIlpkEw20N{s|TP^!PLKrm(6&WO@k7Fk<9JFM#)601cZ8>^4L8_$o? z)QG`Wp?XV-hN7L9%I1rUTHb!xcPPpE+W)*`+FEj==5eM7jKb2kZH-_z=ES{Z$Lhm( z8$!$B>)w9Zt?f=rl;#)KW-wlL5VWrI*n*Jmx^E@|F^VLd%vE{U$gzkqEff9kTr=ZE zD|b9WY_zo6CQ)D|8-m4D3$j%QT0<3Wy$b$wn-1g}6HVhEhc}ay-`pC40)*NMS}_+H zu+1NXj0)_gsuTa#`!$f$%)Wpj`SP3Nd$hWxdY@JmPl9XG9gn3Qhy$J}%!0~=RFP4c zMnaHwFr4%iDT;SviX~i_wm6GVCGWLWM}6?|xxBb7Hy)d1V`Da&{VZ1-!+$O-6AJ;# zypt;l?+d9RwfCotC`iUUY%f&hf#%}Un#Iyb%2|f0k=pW``2zTduRqJ|(*#BHSgKsH zikVnoEDLa^- zM}w)pf6z%z$t+e-^>ViU&f#&xWv=H=_BK}7 z1lG~StkN7|Fx~=!HVc&L8HDCzdI6DD(hnJ1SS4@-5-2rdK7E1f3xgv~1xaa0wR^j4 z+!nq#g`x1r_w$p#2f&it66BpO&5$ajPH>Ph9CPjRk4_B^s?$41Ehg*PIM58)QUTpx zN=z4}L{>v3ukm;+qx7w-&eJYhBuW;zoDG#xabiD)6?-!+#Hk?+6|jb(cJiOtc?jDe!neqNxav`m-|rfqn@KS z7fEHUG=i5cl6_a)vd}8ETv;2pI%karwXfI_?V_1csEXLfX8zyp5VQF)>6Sm_tTie@iSg59>aB{A zo6}>OEm>3lM2r11WT`cLiex5hGbGKUp0*g-jXmdt?aQtejyhvEUqe!s>b&N2bZ*p9 zZbEa&^wDOD&kl0YPDk9YhF3Ty9O7xHjMS1$IIEaF3T|NT?ebXBCu+ScgWPEZO)*X$ z8Fij(lBAcdzAPQ9J4iAxWCBdyI?i$|@jnkv%cY##4P0 zHJ%KDU)>u8E0Fy?f`bEq%?E=b`FUYw&N+NHd0aJ#5Q=K#BcSYj=A=$~#XH^}jLm0B zhEaXtFc`ZJL~z~JkC5A_esZ5Fi=+StZrKl#y()$b>1v|Ec-1%9 zM`yTy+x#Ea5BDF89XhPkl*v#_PnP*v&5Pg$;J@uhc2ETyZIrBMiY_ZJj!9D1?IN(F zF7cKhUek6pNOADT?gvOZIv}3w>cF>EYa)tb&LF^gl{3Z`k8(OP^lfC~%Tvo}rx6y|VV*Eu%b zcMioqpN4!SDuu&8EH7;- z;stE*J$^OmuzcSRBqXmaCxBH>yr0g|y)@s_Qz1R=w zBT6Hk_0w6nIumtx|Fd>g6K`%2&(mIGe+;3`L6ow^$Uz{X-3v}V^Ssh>F2O1c$iY$U zQA4@?YtO=1nI`hy<|+LFO~0+==WDon`&zeK{LDrVophQPRgCd1a z4(a1Oa34$+h{t4VW_f-O`+8Rgeze$ry%nScTL@jme#?|~6>~$e6mtJ2xh9v8Def-5 z&Ul)k2WiVJkupAU-X(Qd`b4yvLw+A{fqiYkGkRo9p#zZI`w=heQH<=*6T7aGdPo2FJeLKX=gwLXf;PW&TlIrO_7c8t5QYGO0Bf%P^p1+yexB<@V_gzi+qA*LO zJZmq#CRA10Dk{nH2)t&#(!9h=r$8&6x}7hh^8hM2}&IzQYq?fI0omi zr#Vhw7y=>!+HB!dnC)#?paGceFcx8n)!p6C-rO6_*P2&v4l_T_OOKhI&nu|kvT_k= z0XhGG0KuvPn%d}qdyr?jnUT?-)qmoM%!9#j|}7j0{vezcnvjN58$KCQ+w4vjTU zD=jVc_cmCqKZg1cClzD8tHCrlAKaW76iq1St4ryytt?}Wg4vjTS@4`lI|03hV7p@6 z-954{aZTxd+`q*se}x>EWYey>5urKx=FRxXPj@+uhTdtEAZN`pOvkwqYUNbZmNj7b zyYKgmlSYbZfc5z-F01sdc_w;R+pj5X+sB<}RybFwQxKG`)S&db?$(4;awLIuHo#|H z0we=dfX5kxYtvhPfG3l!pkpS#@KibZR@hPwjZTJP4zX|cLnS{N}+L_&p7qIenV(+u4c5fY`f6x1-!ymL1SD+qHnA)t9B6{1C+yBvnK0Yd!ZiH*}!$C>wRB(R0z5O8v)o$bl3Xz zna6Ce-z}eT__IY>ux7NmKYO6z+leW^@2Myw7K^y~gF%}K55?>@BgH= zN!;>wCPp>NWLyzlP`rhB%O#h?%ByYD<@dgg_nR zvNeF$(UnAxS3!vfJrnCKGVE2E5fZO2CaBk%9>B#slNWs9FG9mT_r8Jik9p#a3Z`l- z&nm$J9~RqQ^29WTrt~nS!fHPTXxzJVH_0J+P?{Wo5z(3w^y1}WUHunf=hQ4%*d^&> z+qP|^j&0kvZQDj2+qP}nw#}|@E+(d9I--BTzFnE?-7BB$=^^rvc-h(r#6Iz;6&C84 z3Yr4FOi=MJe|?_Xg(`x(22b94N>RjNWo{on>YG!zF*V#Hgt4!Z)vXn>o^$_Uj{ z^t4L5cNA_2`M12#&3w1UO-)nWHPioSI@y1~rFJ1B%hrcqB+yn7R*{XqX%6#(AI()DgYIR)t3fbxY3s@L=-4xT}y9}hzkKk(^ zboBakgITX75eHXbk(Mq9+6UJGHk{TO<)sBtCE1Qdh)AX=gH*^ivskGrESH5^tVPup z^Dqy5lVx%35)jiEVrm5+_{OE;d*|P?MYrTLr$i+adKRz#tTwTSo@+%trZ}n|77)HV zyj`EI?CY_gmhRDd6gLh`rh4X*?&4+8xNP9hH@X`xgZX;Gy=qO?UR6qb9%FTN_i0~> z3p&?Z+S-aQd3Co=V>`Y>@kxqLO{6**5}%@g3%n=xYF#lhyZGk7@;J@iu!6*^lv78*YA> z?5ExAf3P_BFNWtScCA`lDZR7jz>%mpUN)`grRhIsZMl62hQMKv0A(m|ul0rxGGsGX zJ>W?~2k+|TPJP|?Ih*JDi@?7|^W+Ddv{a@vTpexM1`fqUp}j)MpAnOW*anrc&;9hc znF}}Iz<$N=gY-sNks~O*vdoO-Wd8attUJYIBk_b(0O3c?>y8#Jc;KG+ z#PPGfj;4}c5$wsza1rb`S;7KPgqk#L!f;W4k8r5oYp~1l^fEQOf;Z;;kQ3H4+3YI?Hb zx91{U6S8S8{Fr(ET~}%rxCD(P0O>0X6}ea|!4JC617|()YBh?weLn(hMj`Q!*WP-f z<`;3rJT8pkYZ&Yc0d;wYfTj6R?=~&(;k;>`vLe>Lg^X@=X~I@}sk=)_TeI-F(V&Z1 zM=r*f74J9QkxZNoDp$<#LenrRnKfzUF(U$zeSFD`i;jZy%?Quiv2cY??Pmy_iwwNl z@Fl^IL(p~cbU=E37Lk{6%SfA0`)l2?QK&kU$O->m)hiZ0fnXGDOC~e28;og9WE*8|?8s}l=1>VRO4C-3kE^2*?5EA0xQ#>D z%?ETVeS8?F)FuTwHUuR6G+3U+b1!_}vSF_BU1|5sb?;gW2{WTd94X}UTNiy{k^BND zF78G_xF~PR9l)6~S4pNNa(}=3P5@oFy#mclWy^@jsXB*NP-h!VNg39RQPlX<4Axxo|B+RI_F8xPc!vl)f=x%uW}x2T#}a* zB-?+7hNjdT{w)kOTj|U{-PsCefwq`^+`g)GgGn%a7iVb?Ndsbsm(X~Sw z9#3G^TSacyKmQ^FpT;pjNKkR7cqnLOq^evZepFuGqgv=Zxh!i^9=4je zzTey}N4b^0uKbXK)5e4ZjHW$aIctqHy&dth1r~93Huy}Fr|}lJ zL=oYHjqxt(g14#i$k44mth|MxGc*Cl%&b58@yx{B!O_+IEPSh!Xd5iP;lx$?T<$N$ z@Hy(K)<5EG4nYr&5XdqF8Rs5#c6#nm>p`9CcUKA%baI;+grU#mei232WrA--Y;aU^ z&S4OG4f*&gGBuw5cpuOt8%ThA?r(^D(i!>qVVB1k_w48}kJ_rXM+N6psJ7+@Ta>uB z?{+}F%OB+M%1`RLC|93eyU(re^L#jk?a@uaXT~btaCEQ7ATrlMSb)iOr3V2SA+1NU z&Dj}}HPrh#f)B0+ym0pOG6&d#&-1!K?2<2;m|_mBy7WOOnYDc+*<5VCLZeGEJP>EA zy}41us52wP=jvt|0z)^4@HLj8(q6pQnV{p9%RgD3dnv%@MuOVpj)%#UQa2Hvo=!m9uHU6$SO}Geq2DGx&+f;V8GCA969Vx zKC2Dsmhh0 zQw@=Eg0JlGxar6~lNMpDyk^VJi7b!p&J6=NVn2?rv9t!K<812j*Tk{Sk;);rz+&b> z_*K7pC)5`!E6z#8LU{XSpJy)W-%g#;s`paU zX-%70kPB06WbVNo9!``v3fKgX(a? zKYEXfxC_a9-=h@zcH83iQdT}ab!u^RYeB6|nxc|-JD*YzASz5#{qny=;OLPWB(U*)CT>utltovT5)-XZH+I}IdA>IcMC02GxNLe{H~Gi4r4vzLJ4%K@5@rJ8dixVzp)!t}N) zoywvYq?qysz%`Za_O$A)+r?6F2-ats3`L*WQ!qE0k6_C1K-V_slBAwy%i38B<;f1B z-{29i$$|87>24|_G6oSxE+brZek@LtLSrGHj5w_o$1oTfD#4C$Kez%q!4yXQ|Ao{o0pd77^`-pxj*RcB)^boDp+ELk39@6kVp0Oh z^$;<`?h*3%6{dEtVqWj>Vw?DqjT>*(R1)S(QIsg7)za72PxXpAn|3iGL}i+Im|LBn zwM2A(ooA`5ahm({ut%qC?#fzg!>;PAZCEW)d{?{@TvSa+-*ZUD2#i{FPbR`vo;()B z+s0^*gMtZ~bn5=c%enbyH0EX8{ZYG}a&lL#u~IyFiKGyvhBl8m=-3 z1&o#v&1$+YW+1v=6oV>@ENZB9rhAMc{vm|#H-VKmki% z{XyewzBPe(*jylA3x33kd8tr#9Nh4I=htvjU%>p&_@uG%6npAM0HLfAp?1aK_f z$S5_VATOMJEL4ye2DB1G%ZYzCc3mO49mkN`yUVMeN&S_B&93mP*;XN2KA=g ziTmxdy(~HRpjjQ#U++WUdX$be_=IKkuPQveIJooXnD)hG-S~WQc zK)7eLE8k!B_Y_>-Pkl70-}qaw*(WCvi)bgMy(|;2A<@^;IsrKba?y_uTH#9H6T)PfqA(#SYZr)<3%YemnYOaV_?HvQKm#@%1HGDe#q zax7ilEp3Q-Yiufl_(UEJm;bEG0FKZO5>GqUls#2?0jv#uYZzu!=0ie<@>Ngn=pGk>5W^jvB9iq>}Me^)$0 ziG-~POC|q&_L}t~_X@ghwgp7rx-r45K6EDgqHRq+<5k)DNxi8VeqL`$IHW15!eXd2 z%nouz@$=cl40P@*2!3lYZI50`VhtdO_nUi070W(?ydwkSEDex7vfbSX7iMf0)gs+r zx$$Z6Rs&FL!(f;ik&e8V#9p;SX538m-z8Q`mDeKvU zQcBH2l*(m93trPLzVuV@yqVEO!>*R^u@^Bqx<`iKk~<}H*k{}zkKvbJ7EdCeI0MSF zR&4Dnq@DoM2;nTDx^Rzoq|a0H)v}f-?inmz- zzxQ>M=&YYZ=^u$ETJ&XN}^B~<2vLQlOk%rt_LgT_)_OZ0Li(-^-m9MmyyYG!02A*Nu&O52e zOzh{vzX+g6xrIjP%h7@^PLC12n=cCodQLZVeXiWeLNP!bSKDlRiMYH+!n|Bbx_>!m zWerTdx~t7rN&a*O@`W{Gv_kkBhwkzf9%JQsJw}wxhrnbskDp)g znPYnvg{$5iJy2d#1n&5P@v#%NoO56fbfTL%)Ct2%f=r8#)&mTfouR!PH!%t z>8>V6Q1;DFRQgzAhKpKGQM2S=XAy@pGG$QxW?^9nzFEBCyn9B^O!b+LDE&`Yu8l#|NV zM<;|t=G=kU&3E#~P)vilq4F_C%6t?Afz7hT%D}F((^t@MttfqgM zE^Hx>S$-!?qqh)dx@6)~Zlz;d$o7bMcuhbO>=QtxLPL|B6=AEQkQ*NI1SlH5)&>i^ zdfotix-URPK;?xcuiQopg}Nr>4tCWKOj9c48!}A8}AT{%Q;9raB4!QtT9edHLGtn4cYN{);exX@cmzS{<88!x3;crLpyJQ zOst0xT1YtYaf%Fph_p~h6bo$o#`Cwnay3if2wySu+awFMkTGDJ>0`SfH_a$8WpZiX z?c0RaL4nFlR8r<~u0Ij}q8Xu5)pu;2%J6YsSe4I@0p7nLiR_2k9Ycvr{0b);M1yCf z53>bor{Wiwsou;of^WkqrYN6U{;cBlGE<8toqOVgW)2;H30Z;K0q&A2H6wnK4 zg#7LwQoqasH`R`%7s@`Q=kiM7HJE+ixu*m93)r$r#ZX26beI`^_qD=K%Zfz@RDU>k z3d-x`xS2eDm}#l0hko1p(ak%5)5jW-$pebnqk5}&rUtH*9br4F zm1Z1wO*Vd7LG=c9ge}rK!197N<{|Rjioi4D>t-TKGTof!*C#qAo;A1SzB@3VOrOhJ zV(Nz<>M4BOayR^zUGwZBe1u}($viTRq?+~M1 z#}-F!XL~oTGl$(^Jn;wy!cNHb=~tDBZFhh2yv|_#h|-_>Qdcu9M1Pstp`&eT zC98(wv6NJm4IARrI%Q%7wB|M*vvvOKf%ZJS8hztv|Hti5aPo07- zdzF9fd5wVx&wI${1NAXl*L7nh*qHdCUk6_Oa#aoAQCo|Y$4ss1JV&u-uwPF6))AGV zO_a?G=p%F*juQ>YG)_}wia0nU1M4z6I1iBW=8G$K)H@_X#%8yBft|62(^~UcT5O#I zdwg-48HCni=mhlncJG-@f&ktf1#4}SY}2oIrToT%oVjZaT+mNqQ%)w-MJP5%V+Ru2 z#>-~>)#~jx()pwSmOjTSkqJlu7Pz@=e7#COx|X-Ayb-$xm7`$ThYOUR)vm<`9bG-p zj7T5hL(URZaNa8>-#`HP%GV3QEDrolt6lp2?)WUKs?y8cY0r%HK#8lkuZo; zh}XVc*TzW_am-tJjfPbNRdY51KM(Ut+20tb`J=SAQo=nOy-A$L^ub(q1fvBV$|wfK zjpu9OZ%RI5*i95kPo~d%JzaKM6`Ddf>~*?F%nS^mGTaP+W+LGh+CY&W7;l-gvZlEB z3_afmME7-jqHS9F*|e-O>BLQS*cOU0V6I!~MuGE+hIb*w$MqglCC)|iWiRQGUTd8i^60^|)f-C(!k^Nar5N>`eOS4pD)mwfT~<}< z#;d1{TAp;CGyVsFfTA0ToC`v39HzINd^bM3*4wdT^0jZL>eT*2E^P#}xQQ@`BZ?Vx z3V;6Uh@o2T@mD9Z=q{T?1HX|q9*C*}nX?nA?ig@&e*3g%rv?vjXN)gch0EW)A;fKy zh5d_e)>l?kt}sZ3j}6LbJUu}Lip;g25Q$=Iy+D9UHqU`CN4t2};y8}`tM23VYffOb zM9&Hry|vGGIpuJ_Lb?iW2TW(C^zTUlx|RLF^l4Ni2upyve+v^4rXb7WMZLlfsf89j z^6@orVpjR2_wh>!~_%>WNtFILfT9YA!xP5U|%_mFi;&?otUfwcur#cT~7 z2kn4Fw7zaCm43&~Xu9Vmo8nnX$!g6B1D_Wjy-B!Nt$#P@$4fxbTFJjY&7KUE;*^8d zUk&?u3+l-9-P)hu7ELnN-qGsuN1(z!u#E;xU`B5|@ofEiVg?bjUwBmJ?UhVJjAR)Qe6 z6foO~4>K;8`zF!*7JSm&@vmGWbj|N+%co3W5MB%cQ};f9{a3X8KsvW$0K}aa*-V&i z%&hw)YBh3hCjCe~ki8z#Gs(xtD$@vgg__tGkHIZ-cv6rP=_I#1^Cx_dEXpMEnD<~y zIl;ai={f(X_#7G9NabQ=sR7$VxwHQG*Oj0s4BPs8zjQ{5x~f!K+}iT3{`h-Q{ah>V z>ZM>bJD@15ncE;fzhL|;P;7CeI5~+RI{?@NxtLupZRs)BqD^L`KX}#oUqTg<5^FnQ zu78aRW4_buvc0OfK#theAiy;k>VOz-B22?oa&{EFXkEHGLf=pb+NnIutFzj_KTg$4X zzva)MYw_VfVxnrNP&LjeL(v^ug|^mKbhPD4fA-?s3XO{tWw3L+H?O*P6xGUHN3kn!+A{ z6n46^qT1ikSEs`%>u~VYZfAW3^OL0oBD50ZhQ}aIvr*1cu_tV zbTkxHfVtyl-e;hlm&vv~sR6$qF9nc7-3$r?Fs&M~Oj5{@ISKGEWBC(`GJEm}Qe*_k zA>=WPcH*km=4Ix?mxqCEVo_X>j9A5y7=n~`ml2k-DO-Cu@Sp~q1}+;Ct`HuZ$B&rv z*08*Xxwp9=>zrY0PEn)v{l0)yi_!(ceRX-<-1z9!z`h%~h}2@lz;G^gvwj+^$U*nxNt$;dRj^x)|&@{8J_N~>4Fd?Z@N5;iqi@Ef*Xf3ey} zqhC}N;lfUP;^rsQ+-DsaNmw_hOPE&KE#Lf*!$BQozDrDt$6pNJb7l(gC{kXzD&XZQ zbVTfo2+h zoDW8gIbOHF6mKpjbul+Pp&aKGV0RsQfg7-tI(FBX=gU=${03{>k3SjC6gE?7E095L}ecL)(PjU`iFMlYRscQYcx zdd3h$9$EgLAs+-uXJO~;H~ zcMo6>`S&|qL}V{;jVCD`7^&8T@LW;;7u{hgX{F?*bp+YDjrbz zDwcg(u%?UEZI|1<{FJkFlV=`1@P&q~vt6nRT}x*X9SrOoY0aE&?b)}0%H?CfU69J< z=kf^wx(%bwx@Zlw9n2s%!wWpLQQr_o81-3J9536*)}!60qQMg^?Q^z1Orx(K^j_}D zU8%BiZ(%g51G_PiU3Bh>=KD;DO|HUNf{}kzYS3d*^u0cUxCGKC!WrxX|0^ao#NK2R z(#>jwoYk_@71MTert4Hh@0$DFS;(rItvqMB-Ox{jpOrX;Z*)sA%jz53hA-F68arnvp^ySZ-D7l;zBH=d(2W!yy}++W2*<&yD@-6UKIa&;CSR#869z zt;6y;7+1MN*INfYL4-D*gpVrYe$O67B1=%!0yO-0DwS8ZFZQ%MB^>x`%W862DT0bY zWoUo1s?IwSMC!vc3l1OG%QCgXvjxgM{%neAquKQgL#8owE8vUw! zIz26~`w^-bc=z3ots1UIoT>Jzd1bXs@14-vDO{G!Nh)SIl= zCS=WQ0}_8LHfU;<(VkVot98^4Xhc)Q-S|m4l2TynC==7B8Ebd{MpH9jCbx_Olj}?m zM2!g4E=)Su5i5LdeYn z=RG@3-rW0b+jq0n*M|$KypWqbI4FMSwB#D$b;H&-_%TRC?~a|`emo~!{l6yd_P=Ly zL(Iu^j&Bm*@LF@H@1=K(QiX5J^l+xS`d0>q-d~EXW36#&8Sx2T==BHfdDa zK-=Q{^*W+)BsXt&h<&CEYp|&7@UH#H->qnKFr#Xe;r+LvMBaG9l~v5llyy1ZDF~)t zDA#&_i)2rh2KnC+=4??}v@rQ(4|>Oiz5zODP9eRp;@OTumT@aPRrV1)bEV7-kt^6V z*hUuR4a_s=UBI%~Ur&??|Nh0KeP3*lZO3=7$5#6=od96RAW--rt)F<`{biwa-n^z3p&Xlu=~~G@@F-#9mMyKb^AEn+rvGgOLD$6G** z60G`)yNAM2lrS}K0gyjAUIpjjLr0 zf7|?`_aJQm8bwM~ehW(?Yn&BFoA3w0#Z_YS3^P-k{ZUTC!S)-cDapWWlSLswrZ~#o z5(If>YWq-}-znqErwq8qqOW}V`s-)3m`A7TeuCa#v%ZZ+{Wo4_C|$gb1~LLjy}_UeL-*waB|fY z@l4QDkLvze%~Wh_ikB2@W2r17{3ao|uYaEN8<2<^B=N!PR6{~9<_v4>qnt}kFK`Jj z8;^Y~O)l;q)vn{DcyuOZ<_ zcN?laEVpuSuR`&F8er+1bb-I;$Z~sv80@8?3`2&li`^eEz3WBlCRyaT{8@YGZ)cFN z`Ya1P6Y|(*>LAW6kK*WI^ryJN^mc%Y##-b?dKEw<4W9+I41+VpcV==1Q_RG_e@AI$tS7V#fX zfQ!M3Zhp%7Nda>4C;Mi9bS`iB>N6_hX8Cv%#m6uMaaM{jRC!ecM#5=Jms$Sxt^!6- z`9)|Fo|zc1q&MtC2SEo)#8a-Z-ms!Bt_A>{&mFEtO;w)C9>tu3G*pGBcabPpq27HsGkx_6F*sF=iiBcF-t9GM&QU~<`+!~MXw8BXcUAz=CFmFE&iyR1I z&MG1lLcSMOc=;l)EG(rJ_Z=+3^K6$l!!s(v#mTyn3g^Isne&nH7NEsyUNpY zc#l_K&Q8&@E%8(-fUOPPJ#Cm)OS7OT?aqC0}=JWF(DIpNI=1wZg9pYe^_5`R{Pab2*Hm+yP|8h2+ z_O}=wRBo7m*4qAPDAF%G1SPic58Qh=v-uCBKi2T7#~3tcgk8^T z9&;3}f|iK%cfjtv4~y0Yuj5Yvt5QHQ-Gy>Z1B7exz8|Y1b2o=e`A2F-e1|&XdyyMG zh={ny?>=g8oBUW(P5#g^deWhn5eLw%m^yzU+H}s^sPab}lLRvRTAmGlOf)q;v=hi? z%EZ@H%engbCAF;Fr*@H9h}mq8YhMvlc2H`3!(!Un57XLM{H?u5tJ4XHJ+q>A2AbTI}bAVfI=j@G^H;`+3#IglQ;tZS&@-M8< zZ;IND-O+?ZY)k(2g@o|{;{nUVRkeb!(bwfTcPPv`a=sZNER5gO$iNcs;V?P9U-Gc1AH2+g~1CXyIItK~>Fa!?(@Q@4 z)T}1uw8@6hbE#HkBKLlNC^(k-l~=D$-#4FjG}&pX9UR=AweiZG!xxw=-A~}WR(cmV{@`bl9Qom5<>RCT zbo(s1F$_6AU*BikA*3&zZ%}I?HHJ@@;QQizz`n=FU%%=Vfu<>-X%Vm;1@N90O#m@n ziASzffVu*tSX&RYNG%Rgu-2oSn>Cq+{e(Jw8$3k-N&yuqly z;CEQLy%>E6x%}9DKE-9wO8L#=2|tT@1*xa6BKA7&Y#2+3CC&j7s2F4?f|t$3=&HEK ziVxC*N#t{Dp3Oj5p}Ywyq<7nRp#oEZ|4uax;OeG^QUja~^iHg=U8Yj1yEL4!1d63c ziCDz`Jrin5#i?J@kl;>%3M7?6szmBbh8vfwGq%z

    hxlmto}${RD0qsS=X@sb+zcuz~Iq8VYNN3j=3 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

    bmn4cdEn7(hdWAH~z*ZWWh&{OO>FJcY>3Uj|+ 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 literal 0 HcmV?d00001 diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..233f65854740880a656b7e265366b236a9bce80c GIT binary patch literal 4286 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 V=^DWO)FHY=r|1?8!NS+W@GmeeeP#dv literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..f4ac11a --- /dev/null +++ b/index.php @@ -0,0 +1,205 @@ +marker[$name] = microtime(); + } + + // -------------------------------------------------------------------- + + /** + * Calculates the time difference between two marked points. + * + * If the first parameter is empty this function instead returns the + * {elapsed_time} pseudo-variable. This permits the full system + * execution time to be shown in a template. The output class will + * swap the real value for this variable. + * + * @access public + * @param string a particular marked point + * @param string a particular marked point + * @param integer the number of decimal places + * @return mixed + */ + function elapsed_time($point1 = '', $point2 = '', $decimals = 4) + { + if ($point1 == '') + { + return '{elapsed_time}'; + } + + if ( ! isset($this->marker[$point1])) + { + return ''; + } + + if ( ! isset($this->marker[$point2])) + { + $this->marker[$point2] = microtime(); + } + + list($sm, $ss) = explode(' ', $this->marker[$point1]); + list($em, $es) = explode(' ', $this->marker[$point2]); + + return number_format(($em + $es) - ($sm + $ss), $decimals); + } + + // -------------------------------------------------------------------- + + /** + * Memory Usage + * + * This function returns the {memory_usage} pseudo-variable. + * This permits it to be put it anywhere in a template + * without the memory being calculated until the end. + * The output class will swap the real value for this variable. + * + * @access public + * @return string + */ + function memory_usage() + { + return '{memory_usage}'; + } + +} + +// END CI_Benchmark class + +/* End of file Benchmark.php */ +/* Location: ./system/core/Benchmark.php */ \ No newline at end of file diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php new file mode 100644 index 0000000..c16c79c --- /dev/null +++ b/system/core/CodeIgniter.php @@ -0,0 +1,402 @@ + $assign_to_config['subclass_prefix'])); + } + +/* + * ------------------------------------------------------ + * Set a liberal script execution time limit + * ------------------------------------------------------ + */ + if (function_exists("set_time_limit") == TRUE AND @ini_get("safe_mode") == 0) + { + @set_time_limit(300); + } + +/* + * ------------------------------------------------------ + * Start the timer... tick tock tick tock... + * ------------------------------------------------------ + */ + $BM =& load_class('Benchmark', 'core'); + $BM->mark('total_execution_time_start'); + $BM->mark('loading_time:_base_classes_start'); + +/* + * ------------------------------------------------------ + * Instantiate the hooks class + * ------------------------------------------------------ + */ + $EXT =& load_class('Hooks', 'core'); + +/* + * ------------------------------------------------------ + * Is there a "pre_system" hook? + * ------------------------------------------------------ + */ + $EXT->_call_hook('pre_system'); + +/* + * ------------------------------------------------------ + * Instantiate the config class + * ------------------------------------------------------ + */ + $CFG =& load_class('Config', 'core'); + + // Do we have any manually set config items in the index.php file? + if (isset($assign_to_config)) + { + $CFG->_assign_to_config($assign_to_config); + } + +/* + * ------------------------------------------------------ + * Instantiate the UTF-8 class + * ------------------------------------------------------ + * + * Note: Order here is rather important as the UTF-8 + * class needs to be used very early on, but it cannot + * properly determine if UTf-8 can be supported until + * after the Config class is instantiated. + * + */ + + $UNI =& load_class('Utf8', 'core'); + +/* + * ------------------------------------------------------ + * Instantiate the URI class + * ------------------------------------------------------ + */ + $URI =& load_class('URI', 'core'); + +/* + * ------------------------------------------------------ + * Instantiate the routing class and set the routing + * ------------------------------------------------------ + */ + $RTR =& load_class('Router', 'core'); + $RTR->_set_routing(); + + // Set any routing overrides that may exist in the main index file + if (isset($routing)) + { + $RTR->_set_overrides($routing); + } + +/* + * ------------------------------------------------------ + * Instantiate the output class + * ------------------------------------------------------ + */ + $OUT =& load_class('Output', 'core'); + +/* + * ------------------------------------------------------ + * Is there a valid cache file? If so, we're done... + * ------------------------------------------------------ + */ + if ($EXT->_call_hook('cache_override') === FALSE) + { + if ($OUT->_display_cache($CFG, $URI) == TRUE) + { + exit; + } + } + +/* + * ----------------------------------------------------- + * Load the security class for xss and csrf support + * ----------------------------------------------------- + */ + $SEC =& load_class('Security', 'core'); + +/* + * ------------------------------------------------------ + * Load the Input class and sanitize globals + * ------------------------------------------------------ + */ + $IN =& load_class('Input', 'core'); + +/* + * ------------------------------------------------------ + * Load the Language class + * ------------------------------------------------------ + */ + $LANG =& load_class('Lang', 'core'); + +/* + * ------------------------------------------------------ + * Load the app controller and local controller + * ------------------------------------------------------ + * + */ + // Load the base controller class + require BASEPATH.'core/Controller.php'; + + function &get_instance() + { + return CI_Controller::get_instance(); + } + + + if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php')) + { + require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'; + } + + // Load the local application controller + // Note: The Router class automatically validates the controller path using the router->_validate_request(). + // If this include fails it means that the default controller in the Routes.php file is not resolving to something valid. + if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php')) + { + show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); + } + + include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'); + + // Set a mark point for benchmarking + $BM->mark('loading_time:_base_classes_end'); + +/* + * ------------------------------------------------------ + * Security check + * ------------------------------------------------------ + * + * None of the functions in the app controller or the + * loader class can be called via the URI, nor can + * controller functions that begin with an underscore + */ + $class = $RTR->fetch_class(); + $method = $RTR->fetch_method(); + + if ( ! class_exists($class) + OR strncmp($method, '_', 1) == 0 + OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller'))) + ) + { + if ( ! empty($RTR->routes['404_override'])) + { + $x = explode('/', $RTR->routes['404_override']); + $class = $x[0]; + $method = (isset($x[1]) ? $x[1] : 'index'); + if ( ! class_exists($class)) + { + if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) + { + show_404("{$class}/{$method}"); + } + + include_once(APPPATH.'controllers/'.$class.'.php'); + } + } + else + { + show_404("{$class}/{$method}"); + } + } + +/* + * ------------------------------------------------------ + * Is there a "pre_controller" hook? + * ------------------------------------------------------ + */ + $EXT->_call_hook('pre_controller'); + +/* + * ------------------------------------------------------ + * Instantiate the requested controller + * ------------------------------------------------------ + */ + // Mark a start point so we can benchmark the controller + $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start'); + + $CI = new $class(); + +/* + * ------------------------------------------------------ + * Is there a "post_controller_constructor" hook? + * ------------------------------------------------------ + */ + $EXT->_call_hook('post_controller_constructor'); + +/* + * ------------------------------------------------------ + * Call the requested method + * ------------------------------------------------------ + */ + // Is there a "remap" function? If so, we call it instead + if (method_exists($CI, '_remap')) + { + $CI->_remap($method, array_slice($URI->rsegments, 2)); + } + else + { + // is_callable() returns TRUE on some versions of PHP 5 for private and protected + // methods, so we'll use this workaround for consistent behavior + if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI)))) + { + // Check and see if we are using a 404 override and use it. + if ( ! empty($RTR->routes['404_override'])) + { + $x = explode('/', $RTR->routes['404_override']); + $class = $x[0]; + $method = (isset($x[1]) ? $x[1] : 'index'); + if ( ! class_exists($class)) + { + if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) + { + show_404("{$class}/{$method}"); + } + + include_once(APPPATH.'controllers/'.$class.'.php'); + unset($CI); + $CI = new $class(); + } + } + else + { + show_404("{$class}/{$method}"); + } + } + + // Call the requested method. + // Any URI segments present (besides the class/function) will be passed to the method for convenience + call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2)); + } + + + // Mark a benchmark end point + $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); + +/* + * ------------------------------------------------------ + * Is there a "post_controller" hook? + * ------------------------------------------------------ + */ + $EXT->_call_hook('post_controller'); + +/* + * ------------------------------------------------------ + * Send the final rendered output to the browser + * ------------------------------------------------------ + */ + if ($EXT->_call_hook('display_override') === FALSE) + { + $OUT->_display(); + } + +/* + * ------------------------------------------------------ + * Is there a "post_system" hook? + * ------------------------------------------------------ + */ + $EXT->_call_hook('post_system'); + +/* + * ------------------------------------------------------ + * Close the DB connection if one exists + * ------------------------------------------------------ + */ + if (class_exists('CI_DB') AND isset($CI->db)) + { + $CI->db->close(); + } + + +/* End of file CodeIgniter.php */ +/* Location: ./system/core/CodeIgniter.php */ \ No newline at end of file diff --git a/system/core/Common.php b/system/core/Common.php new file mode 100644 index 0000000..07534c5 --- /dev/null +++ b/system/core/Common.php @@ -0,0 +1,564 @@ + 5 +* we'll set a static variable. +* +* @access public +* @param string +* @return bool TRUE if the current version is $version or higher +*/ +if ( ! function_exists('is_php')) +{ + function is_php($version = '5.0.0') + { + static $_is_php; + $version = (string)$version; + + if ( ! isset($_is_php[$version])) + { + $_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0) ? FALSE : TRUE; + } + + return $_is_php[$version]; + } +} + +// ------------------------------------------------------------------------ + +/** + * Tests for file writability + * + * is_writable() returns TRUE on Windows servers when you really can't write to + * the file, based on the read-only attribute. is_writable() is also unreliable + * on Unix servers if safe_mode is on. + * + * @access private + * @return void + */ +if ( ! function_exists('is_really_writable')) +{ + function is_really_writable($file) + { + // If we're on a Unix server with safe_mode off we call is_writable + if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE) + { + return is_writable($file); + } + + // For windows servers and safe_mode "on" installations we'll actually + // write a file then read it. Bah... + if (is_dir($file)) + { + $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100)); + + if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) + { + return FALSE; + } + + fclose($fp); + @chmod($file, DIR_WRITE_MODE); + @unlink($file); + return TRUE; + } + elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) + { + return FALSE; + } + + fclose($fp); + return TRUE; + } +} + +// ------------------------------------------------------------------------ + +/** +* Class registry +* +* This function acts as a singleton. If the requested class does not +* exist it is instantiated and set to a static variable. If it has +* previously been instantiated the variable is returned. +* +* @access public +* @param string the class name being requested +* @param string the directory where the class should be found +* @param string the class name prefix +* @return object +*/ +if ( ! function_exists('load_class')) +{ + function &load_class($class, $directory = 'libraries', $prefix = 'CI_') + { + static $_classes = array(); + + // Does the class exist? If so, we're done... + if (isset($_classes[$class])) + { + return $_classes[$class]; + } + + $name = FALSE; + + // Look for the class first in the local application/libraries folder + // then in the native system/libraries folder + foreach (array(APPPATH, BASEPATH) as $path) + { + if (file_exists($path.$directory.'/'.$class.'.php')) + { + $name = $prefix.$class; + + if (class_exists($name) === FALSE) + { + require($path.$directory.'/'.$class.'.php'); + } + + break; + } + } + + // Is the request a class extension? If so we load it too + if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php')) + { + $name = config_item('subclass_prefix').$class; + + if (class_exists($name) === FALSE) + { + require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'); + } + } + + // Did we find the class? + if ($name === FALSE) + { + // Note: We use exit() rather then show_error() in order to avoid a + // self-referencing loop with the Excptions class + exit('Unable to locate the specified class: '.$class.'.php'); + } + + // Keep track of what we just loaded + is_loaded($class); + + $_classes[$class] = new $name(); + return $_classes[$class]; + } +} + +// -------------------------------------------------------------------- + +/** +* Keeps track of which libraries have been loaded. This function is +* called by the load_class() function above +* +* @access public +* @return array +*/ +if ( ! function_exists('is_loaded')) +{ + function &is_loaded($class = '') + { + static $_is_loaded = array(); + + if ($class != '') + { + $_is_loaded[strtolower($class)] = $class; + } + + return $_is_loaded; + } +} + +// ------------------------------------------------------------------------ + +/** +* Loads the main config.php file +* +* This function lets us grab the config file even if the Config class +* hasn't been instantiated yet +* +* @access private +* @return array +*/ +if ( ! function_exists('get_config')) +{ + function &get_config($replace = array()) + { + static $_config; + + if (isset($_config)) + { + return $_config[0]; + } + + // Is the config file in the environment folder? + if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php')) + { + $file_path = APPPATH.'config/config.php'; + } + + // Fetch the config file + if ( ! file_exists($file_path)) + { + exit('The configuration file does not exist.'); + } + + require($file_path); + + // Does the $config array exist in the file? + if ( ! isset($config) OR ! is_array($config)) + { + exit('Your config file does not appear to be formatted correctly.'); + } + + // Are any values being dynamically replaced? + if (count($replace) > 0) + { + foreach ($replace as $key => $val) + { + if (isset($config[$key])) + { + $config[$key] = $val; + } + } + } + + return $_config[0] =& $config; + } +} + +// ------------------------------------------------------------------------ + +/** +* Returns the specified config item +* +* @access public +* @return mixed +*/ +if ( ! function_exists('config_item')) +{ + function config_item($item) + { + static $_config_item = array(); + + if ( ! isset($_config_item[$item])) + { + $config =& get_config(); + + if ( ! isset($config[$item])) + { + return FALSE; + } + $_config_item[$item] = $config[$item]; + } + + return $_config_item[$item]; + } +} + +// ------------------------------------------------------------------------ + +/** +* Error Handler +* +* This function lets us invoke the exception class and +* display errors using the standard error template located +* in application/errors/errors.php +* This function will send the error page directly to the +* browser and exit. +* +* @access public +* @return void +*/ +if ( ! function_exists('show_error')) +{ + function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered') + { + $_error =& load_class('Exceptions', 'core'); + echo $_error->show_error($heading, $message, 'error_general', $status_code); + exit; + } +} + +// ------------------------------------------------------------------------ + +/** +* 404 Page Handler +* +* This function is similar to the show_error() function above +* However, instead of the standard error template it displays +* 404 errors. +* +* @access public +* @return void +*/ +if ( ! function_exists('show_404')) +{ + function show_404($page = '', $log_error = TRUE) + { + $_error =& load_class('Exceptions', 'core'); + $_error->show_404($page, $log_error); + exit; + } +} + +// ------------------------------------------------------------------------ + +/** +* Error Logging Interface +* +* We use this as a simple mechanism to access the logging +* class and send messages to be logged. +* +* @access public +* @return void +*/ +if ( ! function_exists('log_message')) +{ + function log_message($level = 'error', $message, $php_error = FALSE) + { + static $_log; + + if (config_item('log_threshold') == 0) + { + return; + } + + $_log =& load_class('Log'); + $_log->write_log($level, $message, $php_error); + } +} + +// ------------------------------------------------------------------------ + +/** + * Set HTTP Status Header + * + * @access public + * @param int the status code + * @param string + * @return void + */ +if ( ! function_exists('set_status_header')) +{ + function set_status_header($code = 200, $text = '') + { + $stati = array( + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 307 => 'Temporary Redirect', + + 400 => 'Bad Request', + 401 => 'Unauthorized', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported' + ); + + if ($code == '' OR ! is_numeric($code)) + { + show_error('Status codes must be numeric', 500); + } + + if (isset($stati[$code]) AND $text == '') + { + $text = $stati[$code]; + } + + if ($text == '') + { + show_error('No status text available. Please check your status code number or supply your own message text.', 500); + } + + $server_protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : FALSE; + + if (substr(php_sapi_name(), 0, 3) == 'cgi') + { + header("Status: {$code} {$text}", TRUE); + } + elseif ($server_protocol == 'HTTP/1.1' OR $server_protocol == 'HTTP/1.0') + { + header($server_protocol." {$code} {$text}", TRUE, $code); + } + else + { + header("HTTP/1.1 {$code} {$text}", TRUE, $code); + } + } +} + +// -------------------------------------------------------------------- + +/** +* Exception Handler +* +* This is the custom exception handler that is declaired at the top +* of Codeigniter.php. The main reason we use this is to permit +* PHP errors to be logged in our own log files since the user may +* not have access to server logs. Since this function +* effectively intercepts PHP errors, however, we also need +* to display errors based on the current error_reporting level. +* We do that with the use of a PHP error template. +* +* @access private +* @return void +*/ +if ( ! function_exists('_exception_handler')) +{ + function _exception_handler($severity, $message, $filepath, $line) + { + // We don't bother with "strict" notices since they tend to fill up + // the log file with excess information that isn't normally very helpful. + // For example, if you are running PHP 5 and you use version 4 style + // class functions (without prefixes like "public", "private", etc.) + // you'll get notices telling you that these have been deprecated. + if ($severity == E_STRICT) + { + return; + } + + $_error =& load_class('Exceptions', 'core'); + + // Should we display the error? We'll get the current error_reporting + // level and add its bits with the severity bits to find out. + if (($severity & error_reporting()) == $severity) + { + $_error->show_php_error($severity, $message, $filepath, $line); + } + + // Should we log the error? No? We're done... + if (config_item('log_threshold') == 0) + { + return; + } + + $_error->log_exception($severity, $message, $filepath, $line); + } +} + +// -------------------------------------------------------------------- + +/** + * Remove Invisible Characters + * + * This prevents sandwiching null characters + * between ascii characters, like Java\0script. + * + * @access public + * @param string + * @return string + */ +if ( ! function_exists('remove_invisible_characters')) +{ + function remove_invisible_characters($str, $url_encoded = TRUE) + { + $non_displayables = array(); + + // every control character except newline (dec 10) + // carriage return (dec 13), and horizontal tab (dec 09) + + if ($url_encoded) + { + $non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15 + $non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31 + } + + $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127 + + do + { + $str = preg_replace($non_displayables, '', $str, -1, $count); + } + while ($count); + + return $str; + } +} + +// ------------------------------------------------------------------------ + +/** +* Returns HTML escaped variable +* +* @access public +* @param mixed +* @return mixed +*/ +if ( ! function_exists('html_escape')) +{ + function html_escape($var) + { + if (is_array($var)) + { + return array_map('html_escape', $var); + } + else + { + return htmlspecialchars($var, ENT_QUOTES, config_item('charset')); + } + } +} + +/* End of file Common.php */ +/* Location: ./system/core/Common.php */ \ No newline at end of file diff --git a/system/core/Config.php b/system/core/Config.php new file mode 100644 index 0000000..5dffbf3 --- /dev/null +++ b/system/core/Config.php @@ -0,0 +1,379 @@ +config =& get_config(); + log_message('debug', "Config Class Initialized"); + + // Set the base_url automatically if none was provided + if ($this->config['base_url'] == '') + { + if (isset($_SERVER['HTTP_HOST'])) + { + $base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http'; + $base_url .= '://'. $_SERVER['HTTP_HOST']; + $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); + } + + else + { + $base_url = 'http://localhost/'; + } + + $this->set_item('base_url', $base_url); + } + } + + // -------------------------------------------------------------------- + + /** + * Load Config File + * + * @access public + * @param string the config file name + * @param boolean if configuration values should be loaded into their own section + * @param boolean true if errors should just return false, false if an error message should be displayed + * @return boolean if the file was loaded correctly + */ + function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) + { + $file = ($file == '') ? 'config' : str_replace('.php', '', $file); + $found = FALSE; + $loaded = FALSE; + + $check_locations = defined('ENVIRONMENT') + ? array(ENVIRONMENT.'/'.$file, $file) + : array($file); + + foreach ($this->_config_paths as $path) + { + foreach ($check_locations as $location) + { + $file_path = $path.'config/'.$location.'.php'; + + if (in_array($file_path, $this->is_loaded, TRUE)) + { + $loaded = TRUE; + continue 2; + } + + if (file_exists($file_path)) + { + $found = TRUE; + break; + } + } + + if ($found === FALSE) + { + continue; + } + + include($file_path); + + if ( ! isset($config) OR ! is_array($config)) + { + if ($fail_gracefully === TRUE) + { + return FALSE; + } + show_error('Your '.$file_path.' file does not appear to contain a valid configuration array.'); + } + + if ($use_sections === TRUE) + { + if (isset($this->config[$file])) + { + $this->config[$file] = array_merge($this->config[$file], $config); + } + else + { + $this->config[$file] = $config; + } + } + else + { + $this->config = array_merge($this->config, $config); + } + + $this->is_loaded[] = $file_path; + unset($config); + + $loaded = TRUE; + log_message('debug', 'Config file loaded: '.$file_path); + break; + } + + if ($loaded === FALSE) + { + if ($fail_gracefully === TRUE) + { + return FALSE; + } + show_error('The configuration file '.$file.'.php does not exist.'); + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Fetch a config file item + * + * + * @access public + * @param string the config item name + * @param string the index name + * @param bool + * @return string + */ + function item($item, $index = '') + { + if ($index == '') + { + if ( ! isset($this->config[$item])) + { + return FALSE; + } + + $pref = $this->config[$item]; + } + else + { + if ( ! isset($this->config[$index])) + { + return FALSE; + } + + if ( ! isset($this->config[$index][$item])) + { + return FALSE; + } + + $pref = $this->config[$index][$item]; + } + + return $pref; + } + + // -------------------------------------------------------------------- + + /** + * Fetch a config file item - adds slash after item (if item is not empty) + * + * @access public + * @param string the config item name + * @param bool + * @return string + */ + function slash_item($item) + { + if ( ! isset($this->config[$item])) + { + return FALSE; + } + if( trim($this->config[$item]) == '') + { + return ''; + } + + return rtrim($this->config[$item], '/').'/'; + } + + // -------------------------------------------------------------------- + + /** + * Site URL + * Returns base_url . index_page [. uri_string] + * + * @access public + * @param string the URI string + * @return string + */ + function site_url($uri = '') + { + if ($uri == '') + { + return $this->slash_item('base_url').$this->item('index_page'); + } + + if ($this->item('enable_query_strings') == FALSE) + { + $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix'); + return $this->slash_item('base_url').$this->slash_item('index_page').$this->_uri_string($uri).$suffix; + } + else + { + return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri); + } + } + + // ------------------------------------------------------------- + + /** + * Base URL + * Returns base_url [. uri_string] + * + * @access public + * @param string $uri + * @return string + */ + function base_url($uri = '') + { + return $this->slash_item('base_url').ltrim($this->_uri_string($uri), '/'); + } + + // ------------------------------------------------------------- + + /** + * Build URI string for use in Config::site_url() and Config::base_url() + * + * @access protected + * @param $uri + * @return string + */ + protected function _uri_string($uri) + { + if ($this->item('enable_query_strings') == FALSE) + { + if (is_array($uri)) + { + $uri = implode('/', $uri); + } + $uri = trim($uri, '/'); + } + else + { + if (is_array($uri)) + { + $i = 0; + $str = ''; + foreach ($uri as $key => $val) + { + $prefix = ($i == 0) ? '' : '&'; + $str .= $prefix.$key.'='.$val; + $i++; + } + $uri = $str; + } + } + return $uri; + } + + // -------------------------------------------------------------------- + + /** + * System URL + * + * @access public + * @return string + */ + function system_url() + { + $x = explode("/", preg_replace("|/*(.+?)/*$|", "\\1", BASEPATH)); + return $this->slash_item('base_url').end($x).'/'; + } + + // -------------------------------------------------------------------- + + /** + * Set a config file item + * + * @access public + * @param string the config item key + * @param string the config item value + * @return void + */ + function set_item($item, $value) + { + $this->config[$item] = $value; + } + + // -------------------------------------------------------------------- + + /** + * Assign to Config + * + * This function is called by the front controller (CodeIgniter.php) + * after the Config class is instantiated. It permits config items + * to be assigned or overriden by variables contained in the index.php file + * + * @access private + * @param array + * @return void + */ + function _assign_to_config($items = array()) + { + if (is_array($items)) + { + foreach ($items as $key => $val) + { + $this->set_item($key, $val); + } + } + } +} + +// END CI_Config class + +/* End of file Config.php */ +/* Location: ./system/core/Config.php */ diff --git a/system/core/Controller.php b/system/core/Controller.php new file mode 100644 index 0000000..fddb81e --- /dev/null +++ b/system/core/Controller.php @@ -0,0 +1,64 @@ + $class) + { + $this->$var =& load_class($class); + } + + $this->load =& load_class('Loader', 'core'); + + $this->load->initialize(); + + log_message('debug', "Controller Class Initialized"); + } + + public static function &get_instance() + { + return self::$instance; + } +} +// END Controller class + +/* End of file Controller.php */ +/* Location: ./system/core/Controller.php */ \ No newline at end of file diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php new file mode 100644 index 0000000..869739a --- /dev/null +++ b/system/core/Exceptions.php @@ -0,0 +1,193 @@ + 'Error', + E_WARNING => 'Warning', + E_PARSE => 'Parsing Error', + E_NOTICE => 'Notice', + E_CORE_ERROR => 'Core Error', + E_CORE_WARNING => 'Core Warning', + E_COMPILE_ERROR => 'Compile Error', + E_COMPILE_WARNING => 'Compile Warning', + E_USER_ERROR => 'User Error', + E_USER_WARNING => 'User Warning', + E_USER_NOTICE => 'User Notice', + E_STRICT => 'Runtime Notice' + ); + + + /** + * Constructor + */ + public function __construct() + { + $this->ob_level = ob_get_level(); + // Note: Do not log messages from this constructor. + } + + // -------------------------------------------------------------------- + + /** + * Exception Logger + * + * This function logs PHP generated error messages + * + * @access private + * @param string the error severity + * @param string the error string + * @param string the error filepath + * @param string the error line number + * @return string + */ + function log_exception($severity, $message, $filepath, $line) + { + $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity]; + + log_message('error', 'Severity: '.$severity.' --> '.$message. ' '.$filepath.' '.$line, TRUE); + } + + // -------------------------------------------------------------------- + + /** + * 404 Page Not Found Handler + * + * @access private + * @param string the page + * @param bool log error yes/no + * @return string + */ + function show_404($page = '', $log_error = TRUE) + { + $heading = "404 Page Not Found"; + $message = "The page you requested was not found."; + + // By default we log this, but allow a dev to skip it + if ($log_error) + { + log_message('error', '404 Page Not Found --> '.$page); + } + + echo $this->show_error($heading, $message, 'error_404', 404); + exit; + } + + // -------------------------------------------------------------------- + + /** + * General Error Page + * + * This function takes an error message as input + * (either as a string or an array) and displays + * it using the specified template. + * + * @access private + * @param string the heading + * @param string the message + * @param string the template name + * @param int the status code + * @return string + */ + function show_error($heading, $message, $template = 'error_general', $status_code = 500) + { + set_status_header($status_code); + + $message = '

    '.implode('

    ', ( ! is_array($message)) ? array($message) : $message).'

    '; + + if (ob_get_level() > $this->ob_level + 1) + { + ob_end_flush(); + } + ob_start(); + include(APPPATH.'errors/'.$template.'.php'); + $buffer = ob_get_contents(); + ob_end_clean(); + return $buffer; + } + + // -------------------------------------------------------------------- + + /** + * Native PHP error handler + * + * @access private + * @param string the error severity + * @param string the error string + * @param string the error filepath + * @param string the error line number + * @return string + */ + function show_php_error($severity, $message, $filepath, $line) + { + $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity]; + + $filepath = str_replace("\\", "/", $filepath); + + // For safety reasons we do not show the full file path + if (FALSE !== strpos($filepath, '/')) + { + $x = explode('/', $filepath); + $filepath = $x[count($x)-2].'/'.end($x); + } + + if (ob_get_level() > $this->ob_level + 1) + { + ob_end_flush(); + } + ob_start(); + include(APPPATH.'errors/error_php.php'); + $buffer = ob_get_contents(); + ob_end_clean(); + echo $buffer; + } + + +} +// END Exceptions Class + +/* End of file Exceptions.php */ +/* Location: ./system/core/Exceptions.php */ \ No newline at end of file diff --git a/system/core/Hooks.php b/system/core/Hooks.php new file mode 100644 index 0000000..33f1c03 --- /dev/null +++ b/system/core/Hooks.php @@ -0,0 +1,248 @@ +_initialize(); + log_message('debug', "Hooks Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Initialize the Hooks Preferences + * + * @access private + * @return void + */ + function _initialize() + { + $CFG =& load_class('Config', 'core'); + + // If hooks are not enabled in the config file + // there is nothing else to do + + if ($CFG->item('enable_hooks') == FALSE) + { + return; + } + + // Grab the "hooks" definition file. + // If there are no hooks, we're done. + + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'); + } + elseif (is_file(APPPATH.'config/hooks.php')) + { + include(APPPATH.'config/hooks.php'); + } + + + if ( ! isset($hook) OR ! is_array($hook)) + { + return; + } + + $this->hooks =& $hook; + $this->enabled = TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Call Hook + * + * Calls a particular hook + * + * @access private + * @param string the hook name + * @return mixed + */ + function _call_hook($which = '') + { + if ( ! $this->enabled OR ! isset($this->hooks[$which])) + { + return FALSE; + } + + if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0])) + { + foreach ($this->hooks[$which] as $val) + { + $this->_run_hook($val); + } + } + else + { + $this->_run_hook($this->hooks[$which]); + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Run Hook + * + * Runs a particular hook + * + * @access private + * @param array the hook details + * @return bool + */ + function _run_hook($data) + { + if ( ! is_array($data)) + { + return FALSE; + } + + // ----------------------------------- + // Safety - Prevents run-away loops + // ----------------------------------- + + // If the script being called happens to have the same + // hook call within it a loop can happen + + if ($this->in_progress == TRUE) + { + return; + } + + // ----------------------------------- + // Set file path + // ----------------------------------- + + if ( ! isset($data['filepath']) OR ! isset($data['filename'])) + { + return FALSE; + } + + $filepath = APPPATH.$data['filepath'].'/'.$data['filename']; + + if ( ! file_exists($filepath)) + { + return FALSE; + } + + // ----------------------------------- + // Set class/function name + // ----------------------------------- + + $class = FALSE; + $function = FALSE; + $params = ''; + + if (isset($data['class']) AND $data['class'] != '') + { + $class = $data['class']; + } + + if (isset($data['function'])) + { + $function = $data['function']; + } + + if (isset($data['params'])) + { + $params = $data['params']; + } + + if ($class === FALSE AND $function === FALSE) + { + return FALSE; + } + + // ----------------------------------- + // Set the in_progress flag + // ----------------------------------- + + $this->in_progress = TRUE; + + // ----------------------------------- + // Call the requested class and/or function + // ----------------------------------- + + if ($class !== FALSE) + { + if ( ! class_exists($class)) + { + require($filepath); + } + + $HOOK = new $class; + $HOOK->$function($params); + } + else + { + if ( ! function_exists($function)) + { + require($filepath); + } + + $function($params); + } + + $this->in_progress = FALSE; + return TRUE; + } + +} + +// END CI_Hooks class + +/* End of file Hooks.php */ +/* Location: ./system/core/Hooks.php */ \ No newline at end of file diff --git a/system/core/Input.php b/system/core/Input.php new file mode 100644 index 0000000..0c1f2b0 --- /dev/null +++ b/system/core/Input.php @@ -0,0 +1,849 @@ +_allow_get_array = (config_item('allow_get_array') === TRUE); + $this->_enable_xss = (config_item('global_xss_filtering') === TRUE); + $this->_enable_csrf = (config_item('csrf_protection') === TRUE); + + global $SEC; + $this->security =& $SEC; + + // Do we need the UTF-8 class? + if (UTF8_ENABLED === TRUE) + { + global $UNI; + $this->uni =& $UNI; + } + + // Sanitize global arrays + $this->_sanitize_globals(); + } + + // -------------------------------------------------------------------- + + /** + * Fetch from array + * + * This is a helper function to retrieve values from global arrays + * + * @access private + * @param array + * @param string + * @param bool + * @return string + */ + function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE) + { + if ( ! isset($array[$index])) + { + return FALSE; + } + + if ($xss_clean === TRUE) + { + return $this->security->xss_clean($array[$index]); + } + + return $array[$index]; + } + + // -------------------------------------------------------------------- + + /** + * Fetch an item from the GET array + * + * @access public + * @param string + * @param bool + * @return string + */ + function get($index = NULL, $xss_clean = FALSE) + { + // Check if a field has been provided + if ($index === NULL AND ! empty($_GET)) + { + $get = array(); + + // loop through the full _GET array + foreach (array_keys($_GET) as $key) + { + $get[$key] = $this->_fetch_from_array($_GET, $key, $xss_clean); + } + return $get; + } + + return $this->_fetch_from_array($_GET, $index, $xss_clean); + } + + // -------------------------------------------------------------------- + + /** + * Fetch an item from the POST array + * + * @access public + * @param string + * @param bool + * @return string + */ + function post($index = NULL, $xss_clean = FALSE) + { + // Check if a field has been provided + if ($index === NULL AND ! empty($_POST)) + { + $post = array(); + + // Loop through the full _POST array and return it + foreach (array_keys($_POST) as $key) + { + $post[$key] = $this->_fetch_from_array($_POST, $key, $xss_clean); + } + return $post; + } + + return $this->_fetch_from_array($_POST, $index, $xss_clean); + } + + + // -------------------------------------------------------------------- + + /** + * Fetch an item from either the GET array or the POST + * + * @access public + * @param string The index key + * @param bool XSS cleaning + * @return string + */ + function get_post($index = '', $xss_clean = FALSE) + { + if ( ! isset($_POST[$index]) ) + { + return $this->get($index, $xss_clean); + } + else + { + return $this->post($index, $xss_clean); + } + } + + // -------------------------------------------------------------------- + + /** + * Fetch an item from the COOKIE array + * + * @access public + * @param string + * @param bool + * @return string + */ + function cookie($index = '', $xss_clean = FALSE) + { + return $this->_fetch_from_array($_COOKIE, $index, $xss_clean); + } + + // ------------------------------------------------------------------------ + + /** + * Set cookie + * + * Accepts six parameter, or you can submit an associative + * array in the first parameter containing all the values. + * + * @access public + * @param mixed + * @param string the value of the cookie + * @param string the number of seconds until expiration + * @param string the cookie domain. Usually: .yourdomain.com + * @param string the cookie path + * @param string the cookie prefix + * @param bool true makes the cookie secure + * @return void + */ + function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE) + { + if (is_array($name)) + { + // always leave 'name' in last place, as the loop will break otherwise, due to $$item + foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'name') as $item) + { + if (isset($name[$item])) + { + $$item = $name[$item]; + } + } + } + + if ($prefix == '' AND config_item('cookie_prefix') != '') + { + $prefix = config_item('cookie_prefix'); + } + if ($domain == '' AND config_item('cookie_domain') != '') + { + $domain = config_item('cookie_domain'); + } + if ($path == '/' AND config_item('cookie_path') != '/') + { + $path = config_item('cookie_path'); + } + if ($secure == FALSE AND config_item('cookie_secure') != FALSE) + { + $secure = config_item('cookie_secure'); + } + + if ( ! is_numeric($expire)) + { + $expire = time() - 86500; + } + else + { + $expire = ($expire > 0) ? time() + $expire : 0; + } + + setcookie($prefix.$name, $value, $expire, $path, $domain, $secure); + } + + // -------------------------------------------------------------------- + + /** + * Fetch an item from the SERVER array + * + * @access public + * @param string + * @param bool + * @return string + */ + function server($index = '', $xss_clean = FALSE) + { + return $this->_fetch_from_array($_SERVER, $index, $xss_clean); + } + + // -------------------------------------------------------------------- + + /** + * Fetch the IP Address + * + * @return string + */ + public function ip_address() + { + if ($this->ip_address !== FALSE) + { + return $this->ip_address; + } + + $proxy_ips = config_item('proxy_ips'); + if ( ! empty($proxy_ips)) + { + $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips)); + foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header) + { + if (($spoof = $this->server($header)) !== FALSE) + { + // Some proxies typically list the whole chain of IP + // addresses through which the client has reached us. + // e.g. client_ip, proxy_ip1, proxy_ip2, etc. + if (strpos($spoof, ',') !== FALSE) + { + $spoof = explode(',', $spoof, 2); + $spoof = $spoof[0]; + } + + if ( ! $this->valid_ip($spoof)) + { + $spoof = FALSE; + } + else + { + break; + } + } + } + + $this->ip_address = ($spoof !== FALSE && in_array($_SERVER['REMOTE_ADDR'], $proxy_ips, TRUE)) + ? $spoof : $_SERVER['REMOTE_ADDR']; + } + else + { + $this->ip_address = $_SERVER['REMOTE_ADDR']; + } + + if ( ! $this->valid_ip($this->ip_address)) + { + $this->ip_address = '0.0.0.0'; + } + + return $this->ip_address; + } + + // -------------------------------------------------------------------- + + /** + * Validate IP Address + * + * @access public + * @param string + * @param string ipv4 or ipv6 + * @return bool + */ + public function valid_ip($ip, $which = '') + { + $which = strtolower($which); + + // First check if filter_var is available + if (is_callable('filter_var')) + { + switch ($which) { + case 'ipv4': + $flag = FILTER_FLAG_IPV4; + break; + case 'ipv6': + $flag = FILTER_FLAG_IPV6; + break; + default: + $flag = ''; + break; + } + + return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flag); + } + + if ($which !== 'ipv6' && $which !== 'ipv4') + { + if (strpos($ip, ':') !== FALSE) + { + $which = 'ipv6'; + } + elseif (strpos($ip, '.') !== FALSE) + { + $which = 'ipv4'; + } + else + { + return FALSE; + } + } + + $func = '_valid_'.$which; + return $this->$func($ip); + } + + // -------------------------------------------------------------------- + + /** + * Validate IPv4 Address + * + * Updated version suggested by Geert De Deckere + * + * @access protected + * @param string + * @return bool + */ + protected function _valid_ipv4($ip) + { + $ip_segments = explode('.', $ip); + + // Always 4 segments needed + if (count($ip_segments) !== 4) + { + return FALSE; + } + // IP can not start with 0 + if ($ip_segments[0][0] == '0') + { + return FALSE; + } + + // Check each segment + foreach ($ip_segments as $segment) + { + // IP segments must be digits and can not be + // longer than 3 digits or greater then 255 + if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3) + { + return FALSE; + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Validate IPv6 Address + * + * @access protected + * @param string + * @return bool + */ + protected function _valid_ipv6($str) + { + // 8 groups, separated by : + // 0-ffff per group + // one set of consecutive 0 groups can be collapsed to :: + + $groups = 8; + $collapsed = FALSE; + + $chunks = array_filter( + preg_split('/(:{1,2})/', $str, NULL, PREG_SPLIT_DELIM_CAPTURE) + ); + + // Rule out easy nonsense + if (current($chunks) == ':' OR end($chunks) == ':') + { + return FALSE; + } + + // PHP supports IPv4-mapped IPv6 addresses, so we'll expect those as well + if (strpos(end($chunks), '.') !== FALSE) + { + $ipv4 = array_pop($chunks); + + if ( ! $this->_valid_ipv4($ipv4)) + { + return FALSE; + } + + $groups--; + } + + while ($seg = array_pop($chunks)) + { + if ($seg[0] == ':') + { + if (--$groups == 0) + { + return FALSE; // too many groups + } + + if (strlen($seg) > 2) + { + return FALSE; // long separator + } + + if ($seg == '::') + { + if ($collapsed) + { + return FALSE; // multiple collapsed + } + + $collapsed = TRUE; + } + } + elseif (preg_match("/[^0-9a-f]/i", $seg) OR strlen($seg) > 4) + { + return FALSE; // invalid segment + } + } + + return $collapsed OR $groups == 1; + } + + // -------------------------------------------------------------------- + + /** + * User Agent + * + * @access public + * @return string + */ + function user_agent() + { + if ($this->user_agent !== FALSE) + { + return $this->user_agent; + } + + $this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT']; + + return $this->user_agent; + } + + // -------------------------------------------------------------------- + + /** + * Sanitize Globals + * + * This function does the following: + * + * Unsets $_GET data (if query strings are not enabled) + * + * Unsets all globals if register_globals is enabled + * + * Standardizes newline characters to \n + * + * @access private + * @return void + */ + function _sanitize_globals() + { + // It would be "wrong" to unset any of these GLOBALS. + $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', + '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA', + 'system_folder', 'application_folder', 'BM', 'EXT', + 'CFG', 'URI', 'RTR', 'OUT', 'IN'); + + // Unset globals for securiy. + // This is effectively the same as register_globals = off + foreach (array($_GET, $_POST, $_COOKIE) as $global) + { + if ( ! is_array($global)) + { + if ( ! in_array($global, $protected)) + { + global $$global; + $$global = NULL; + } + } + else + { + foreach ($global as $key => $val) + { + if ( ! in_array($key, $protected)) + { + global $$key; + $$key = NULL; + } + } + } + } + + // Is $_GET data allowed? If not we'll set the $_GET to an empty array + if ($this->_allow_get_array == FALSE) + { + $_GET = array(); + } + else + { + if (is_array($_GET) AND count($_GET) > 0) + { + foreach ($_GET as $key => $val) + { + $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + } + } + } + + // Clean $_POST Data + if (is_array($_POST) AND count($_POST) > 0) + { + foreach ($_POST as $key => $val) + { + $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + } + } + + // Clean $_COOKIE Data + if (is_array($_COOKIE) AND count($_COOKIE) > 0) + { + // Also get rid of specially treated cookies that might be set by a server + // or silly application, that are of no use to a CI application anyway + // but that when present will trip our 'Disallowed Key Characters' alarm + // http://www.ietf.org/rfc/rfc2109.txt + // note that the key names below are single quoted strings, and are not PHP variables + unset($_COOKIE['$Version']); + unset($_COOKIE['$Path']); + unset($_COOKIE['$Domain']); + + foreach ($_COOKIE as $key => $val) + { + $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + } + } + + // Sanitize PHP_SELF + $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']); + + + // CSRF Protection check on HTTP requests + if ($this->_enable_csrf == TRUE && ! $this->is_cli_request()) + { + $this->security->csrf_verify(); + } + + log_message('debug', "Global POST and COOKIE data sanitized"); + } + + // -------------------------------------------------------------------- + + /** + * Clean Input Data + * + * This is a helper function. It escapes data and + * standardizes newline characters to \n + * + * @access private + * @param string + * @return string + */ + function _clean_input_data($str) + { + if (is_array($str)) + { + $new_array = array(); + foreach ($str as $key => $val) + { + $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + } + return $new_array; + } + + /* We strip slashes if magic quotes is on to keep things consistent + + NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and + it will probably not exist in future versions at all. + */ + if ( ! is_php('5.4') && get_magic_quotes_gpc()) + { + $str = stripslashes($str); + } + + // Clean UTF-8 if supported + if (UTF8_ENABLED === TRUE) + { + $str = $this->uni->clean_string($str); + } + + // Remove control characters + $str = remove_invisible_characters($str); + + // Should we filter the input data? + if ($this->_enable_xss === TRUE) + { + $str = $this->security->xss_clean($str); + } + + // Standardize newlines if needed + if ($this->_standardize_newlines == TRUE) + { + if (strpos($str, "\r") !== FALSE) + { + $str = str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str); + } + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Clean Keys + * + * This is a helper function. To prevent malicious users + * from trying to exploit keys we make sure that keys are + * only named with alpha-numeric text and a few other items. + * + * @access private + * @param string + * @return string + */ + function _clean_input_keys($str) + { + if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str)) + { + exit('Disallowed Key Characters.'); + } + + // Clean UTF-8 if supported + if (UTF8_ENABLED === TRUE) + { + $str = $this->uni->clean_string($str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Request Headers + * + * In Apache, you can simply call apache_request_headers(), however for + * people running other webservers the function is undefined. + * + * @param bool XSS cleaning + * + * @return array + */ + public function request_headers($xss_clean = FALSE) + { + // Look at Apache go! + if (function_exists('apache_request_headers')) + { + $headers = apache_request_headers(); + } + else + { + $headers['Content-Type'] = (isset($_SERVER['CONTENT_TYPE'])) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE'); + + foreach ($_SERVER as $key => $val) + { + if (strncmp($key, 'HTTP_', 5) === 0) + { + $headers[substr($key, 5)] = $this->_fetch_from_array($_SERVER, $key, $xss_clean); + } + } + } + + // take SOME_HEADER and turn it into Some-Header + foreach ($headers as $key => $val) + { + $key = str_replace('_', ' ', strtolower($key)); + $key = str_replace(' ', '-', ucwords($key)); + + $this->headers[$key] = $val; + } + + return $this->headers; + } + + // -------------------------------------------------------------------- + + /** + * Get Request Header + * + * Returns the value of a single member of the headers class member + * + * @param string array key for $this->headers + * @param boolean XSS Clean or not + * @return mixed FALSE on failure, string on success + */ + public function get_request_header($index, $xss_clean = FALSE) + { + if (empty($this->headers)) + { + $this->request_headers(); + } + + if ( ! isset($this->headers[$index])) + { + return FALSE; + } + + if ($xss_clean === TRUE) + { + return $this->security->xss_clean($this->headers[$index]); + } + + return $this->headers[$index]; + } + + // -------------------------------------------------------------------- + + /** + * Is ajax Request? + * + * Test to see if a request contains the HTTP_X_REQUESTED_WITH header + * + * @return boolean + */ + public function is_ajax_request() + { + return ($this->server('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest'); + } + + // -------------------------------------------------------------------- + + /** + * Is cli Request? + * + * Test to see if a request was made from the command line + * + * @return bool + */ + public function is_cli_request() + { + return (php_sapi_name() === 'cli' OR defined('STDIN')); + } + +} + +/* End of file Input.php */ +/* Location: ./system/core/Input.php */ \ No newline at end of file diff --git a/system/core/Lang.php b/system/core/Lang.php new file mode 100644 index 0000000..5ac6718 --- /dev/null +++ b/system/core/Lang.php @@ -0,0 +1,160 @@ +is_loaded, TRUE)) + { + return; + } + + $config =& get_config(); + + if ($idiom == '') + { + $deft_lang = ( ! isset($config['language'])) ? 'english' : $config['language']; + $idiom = ($deft_lang == '') ? 'english' : $deft_lang; + } + + // Determine where the language file is and load it + if ($alt_path != '' && file_exists($alt_path.'language/'.$idiom.'/'.$langfile)) + { + include($alt_path.'language/'.$idiom.'/'.$langfile); + } + else + { + $found = FALSE; + + foreach (get_instance()->load->get_package_paths(TRUE) as $package_path) + { + if (file_exists($package_path.'language/'.$idiom.'/'.$langfile)) + { + include($package_path.'language/'.$idiom.'/'.$langfile); + $found = TRUE; + break; + } + } + + if ($found !== TRUE) + { + show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile); + } + } + + + if ( ! isset($lang)) + { + log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile); + return; + } + + if ($return == TRUE) + { + return $lang; + } + + $this->is_loaded[] = $langfile; + $this->language = array_merge($this->language, $lang); + unset($lang); + + log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Fetch a single line of text from the language array + * + * @access public + * @param string $line the language line + * @return string + */ + function line($line = '') + { + $value = ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line]; + + // Because killer robots like unicorns! + if ($value === FALSE) + { + log_message('error', 'Could not find the language line "'.$line.'"'); + } + + return $value; + } + +} +// END Language Class + +/* End of file Lang.php */ +/* Location: ./system/core/Lang.php */ diff --git a/system/core/Loader.php b/system/core/Loader.php new file mode 100644 index 0000000..6b7ee0c --- /dev/null +++ b/system/core/Loader.php @@ -0,0 +1,1248 @@ + 'unit', + 'user_agent' => 'agent'); + + /** + * Constructor + * + * Sets the path to the view files and gets the initial output buffering level + */ + public function __construct() + { + $this->_ci_ob_level = ob_get_level(); + $this->_ci_library_paths = array(APPPATH, BASEPATH); + $this->_ci_helper_paths = array(APPPATH, BASEPATH); + $this->_ci_model_paths = array(APPPATH); + $this->_ci_view_paths = array(APPPATH.'views/' => TRUE); + + log_message('debug', "Loader Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Initialize the Loader + * + * This method is called once in CI_Controller. + * + * @param array + * @return object + */ + public function initialize() + { + $this->_ci_classes = array(); + $this->_ci_loaded_files = array(); + $this->_ci_models = array(); + $this->_base_classes =& is_loaded(); + + $this->_ci_autoloader(); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Is Loaded + * + * A utility function to test if a class is in the self::$_ci_classes array. + * This function returns the object name if the class tested for is loaded, + * and returns FALSE if it isn't. + * + * It is mainly used in the form_helper -> _get_validation_object() + * + * @param string class being checked for + * @return mixed class object name on the CI SuperObject or FALSE + */ + public function is_loaded($class) + { + if (isset($this->_ci_classes[$class])) + { + return $this->_ci_classes[$class]; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Class Loader + * + * This function lets users load and instantiate classes. + * It is designed to be called from a user's app controllers. + * + * @param string the name of the class + * @param mixed the optional parameters + * @param string an optional object name + * @return void + */ + public function library($library = '', $params = NULL, $object_name = NULL) + { + if (is_array($library)) + { + foreach ($library as $class) + { + $this->library($class, $params); + } + + return; + } + + if ($library == '' OR isset($this->_base_classes[$library])) + { + return FALSE; + } + + if ( ! is_null($params) && ! is_array($params)) + { + $params = NULL; + } + + $this->_ci_load_class($library, $params, $object_name); + } + + // -------------------------------------------------------------------- + + /** + * Model Loader + * + * This function lets users load and instantiate models. + * + * @param string the name of the class + * @param string name for the model + * @param bool database connection + * @return void + */ + public function model($model, $name = '', $db_conn = FALSE) + { + if (is_array($model)) + { + foreach ($model as $babe) + { + $this->model($babe); + } + return; + } + + if ($model == '') + { + return; + } + + $path = ''; + + // Is the model in a sub-folder? If so, parse out the filename and path. + if (($last_slash = strrpos($model, '/')) !== FALSE) + { + // The path is in front of the last slash + $path = substr($model, 0, $last_slash + 1); + + // And the model name behind it + $model = substr($model, $last_slash + 1); + } + + if ($name == '') + { + $name = $model; + } + + if (in_array($name, $this->_ci_models, TRUE)) + { + return; + } + + $CI =& get_instance(); + if (isset($CI->$name)) + { + show_error('The model name you are loading is the name of a resource that is already being used: '.$name); + } + + $model = strtolower($model); + + foreach ($this->_ci_model_paths as $mod_path) + { + if ( ! file_exists($mod_path.'models/'.$path.$model.'.php')) + { + continue; + } + + if ($db_conn !== FALSE AND ! class_exists('CI_DB')) + { + if ($db_conn === TRUE) + { + $db_conn = ''; + } + + $CI->load->database($db_conn, FALSE, TRUE); + } + + if ( ! class_exists('CI_Model')) + { + load_class('Model', 'core'); + } + + require_once($mod_path.'models/'.$path.$model.'.php'); + + $model = ucfirst($model); + + $CI->$name = new $model(); + + $this->_ci_models[] = $name; + return; + } + + // couldn't find the model + show_error('Unable to locate the model you have specified: '.$model); + } + + // -------------------------------------------------------------------- + + /** + * Database Loader + * + * @param string the DB credentials + * @param bool whether to return the DB object + * @param bool whether to enable active record (this allows us to override the config setting) + * @return object + */ + public function database($params = '', $return = FALSE, $active_record = NULL) + { + // Grab the super object + $CI =& get_instance(); + + // Do we even need to load the database class? + if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db)) + { + return FALSE; + } + + require_once(BASEPATH.'database/DB.php'); + + if ($return === TRUE) + { + return DB($params, $active_record); + } + + // Initialize the db variable. Needed to prevent + // reference errors with some configurations + $CI->db = ''; + + // Load the DB class + $CI->db =& DB($params, $active_record); + } + + // -------------------------------------------------------------------- + + /** + * Load the Utilities Class + * + * @return string + */ + public function dbutil() + { + if ( ! class_exists('CI_DB')) + { + $this->database(); + } + + $CI =& get_instance(); + + // for backwards compatibility, load dbforge so we can extend dbutils off it + // this use is deprecated and strongly discouraged + $CI->load->dbforge(); + + require_once(BASEPATH.'database/DB_utility.php'); + require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility.php'); + $class = 'CI_DB_'.$CI->db->dbdriver.'_utility'; + + $CI->dbutil = new $class(); + } + + // -------------------------------------------------------------------- + + /** + * Load the Database Forge Class + * + * @return string + */ + public function dbforge() + { + if ( ! class_exists('CI_DB')) + { + $this->database(); + } + + $CI =& get_instance(); + + require_once(BASEPATH.'database/DB_forge.php'); + require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge.php'); + $class = 'CI_DB_'.$CI->db->dbdriver.'_forge'; + + $CI->dbforge = new $class(); + } + + // -------------------------------------------------------------------- + + /** + * Load View + * + * This function is used to load a "view" file. It has three parameters: + * + * 1. The name of the "view" file to be included. + * 2. An associative array of data to be extracted for use in the view. + * 3. TRUE/FALSE - whether to return the data or load it. In + * some cases it's advantageous to be able to return data so that + * a developer can process it in some way. + * + * @param string + * @param array + * @param bool + * @return void + */ + public function view($view, $vars = array(), $return = FALSE) + { + return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return)); + } + + // -------------------------------------------------------------------- + + /** + * Load File + * + * This is a generic file loader + * + * @param string + * @param bool + * @return string + */ + public function file($path, $return = FALSE) + { + return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return)); + } + + // -------------------------------------------------------------------- + + /** + * Set Variables + * + * Once variables are set they become available within + * the controller class and its "view" files. + * + * @param array + * @param string + * @return void + */ + public function vars($vars = array(), $val = '') + { + if ($val != '' AND is_string($vars)) + { + $vars = array($vars => $val); + } + + $vars = $this->_ci_object_to_array($vars); + + if (is_array($vars) AND count($vars) > 0) + { + foreach ($vars as $key => $val) + { + $this->_ci_cached_vars[$key] = $val; + } + } + } + + // -------------------------------------------------------------------- + + /** + * Get Variable + * + * Check if a variable is set and retrieve it. + * + * @param array + * @return void + */ + public function get_var($key) + { + return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL; + } + + // -------------------------------------------------------------------- + + /** + * Load Helper + * + * This function loads the specified helper file. + * + * @param mixed + * @return void + */ + public function helper($helpers = array()) + { + foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper) + { + if (isset($this->_ci_helpers[$helper])) + { + continue; + } + + $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.'.php'; + + // Is this a helper extension request? + if (file_exists($ext_helper)) + { + $base_helper = BASEPATH.'helpers/'.$helper.'.php'; + + if ( ! file_exists($base_helper)) + { + show_error('Unable to load the requested file: helpers/'.$helper.'.php'); + } + + include_once($ext_helper); + include_once($base_helper); + + $this->_ci_helpers[$helper] = TRUE; + log_message('debug', 'Helper loaded: '.$helper); + continue; + } + + // Try to load the helper + foreach ($this->_ci_helper_paths as $path) + { + if (file_exists($path.'helpers/'.$helper.'.php')) + { + include_once($path.'helpers/'.$helper.'.php'); + + $this->_ci_helpers[$helper] = TRUE; + log_message('debug', 'Helper loaded: '.$helper); + break; + } + } + + // unable to load the helper + if ( ! isset($this->_ci_helpers[$helper])) + { + show_error('Unable to load the requested file: helpers/'.$helper.'.php'); + } + } + } + + // -------------------------------------------------------------------- + + /** + * Load Helpers + * + * This is simply an alias to the above function in case the + * user has written the plural form of this function. + * + * @param array + * @return void + */ + public function helpers($helpers = array()) + { + $this->helper($helpers); + } + + // -------------------------------------------------------------------- + + /** + * Loads a language file + * + * @param array + * @param string + * @return void + */ + public function language($file = array(), $lang = '') + { + $CI =& get_instance(); + + if ( ! is_array($file)) + { + $file = array($file); + } + + foreach ($file as $langfile) + { + $CI->lang->load($langfile, $lang); + } + } + + // -------------------------------------------------------------------- + + /** + * Loads a config file + * + * @param string + * @param bool + * @param bool + * @return void + */ + public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) + { + $CI =& get_instance(); + $CI->config->load($file, $use_sections, $fail_gracefully); + } + + // -------------------------------------------------------------------- + + /** + * Driver + * + * Loads a driver library + * + * @param string the name of the class + * @param mixed the optional parameters + * @param string an optional object name + * @return void + */ + public function driver($library = '', $params = NULL, $object_name = NULL) + { + if ( ! class_exists('CI_Driver_Library')) + { + // we aren't instantiating an object here, that'll be done by the Library itself + require BASEPATH.'libraries/Driver.php'; + } + + if ($library == '') + { + return FALSE; + } + + // We can save the loader some time since Drivers will *always* be in a subfolder, + // and typically identically named to the library + if ( ! strpos($library, '/')) + { + $library = ucfirst($library).'/'.$library; + } + + return $this->library($library, $params, $object_name); + } + + // -------------------------------------------------------------------- + + /** + * Add Package Path + * + * Prepends a parent path to the library, model, helper, and config path arrays + * + * @param string + * @param boolean + * @return void + */ + public function add_package_path($path, $view_cascade=TRUE) + { + $path = rtrim($path, '/').'/'; + + array_unshift($this->_ci_library_paths, $path); + array_unshift($this->_ci_model_paths, $path); + array_unshift($this->_ci_helper_paths, $path); + + $this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths; + + // Add config file path + $config =& $this->_ci_get_component('config'); + array_unshift($config->_config_paths, $path); + } + + // -------------------------------------------------------------------- + + /** + * Get Package Paths + * + * Return a list of all package paths, by default it will ignore BASEPATH. + * + * @param string + * @return void + */ + public function get_package_paths($include_base = FALSE) + { + return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths; + } + + // -------------------------------------------------------------------- + + /** + * Remove Package Path + * + * Remove a path from the library, model, and helper path arrays if it exists + * If no path is provided, the most recently added path is removed. + * + * @param type + * @param bool + * @return type + */ + public function remove_package_path($path = '', $remove_config_path = TRUE) + { + $config =& $this->_ci_get_component('config'); + + if ($path == '') + { + $void = array_shift($this->_ci_library_paths); + $void = array_shift($this->_ci_model_paths); + $void = array_shift($this->_ci_helper_paths); + $void = array_shift($this->_ci_view_paths); + $void = array_shift($config->_config_paths); + } + else + { + $path = rtrim($path, '/').'/'; + foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var) + { + if (($key = array_search($path, $this->{$var})) !== FALSE) + { + unset($this->{$var}[$key]); + } + } + + if (isset($this->_ci_view_paths[$path.'views/'])) + { + unset($this->_ci_view_paths[$path.'views/']); + } + + if (($key = array_search($path, $config->_config_paths)) !== FALSE) + { + unset($config->_config_paths[$key]); + } + } + + // make sure the application default paths are still in the array + $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH))); + $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH))); + $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH))); + $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE)); + $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH))); + } + + // -------------------------------------------------------------------- + + /** + * Loader + * + * This function is used to load views and files. + * Variables are prefixed with _ci_ to avoid symbol collision with + * variables made available to view files + * + * @param array + * @return void + */ + protected function _ci_load($_ci_data) + { + // Set the default data variables + foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val) + { + $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val]; + } + + $file_exists = FALSE; + + // Set the path to the requested file + if ($_ci_path != '') + { + $_ci_x = explode('/', $_ci_path); + $_ci_file = end($_ci_x); + } + else + { + $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION); + $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view; + + foreach ($this->_ci_view_paths as $view_file => $cascade) + { + if (file_exists($view_file.$_ci_file)) + { + $_ci_path = $view_file.$_ci_file; + $file_exists = TRUE; + break; + } + + if ( ! $cascade) + { + break; + } + } + } + + if ( ! $file_exists && ! file_exists($_ci_path)) + { + show_error('Unable to load the requested file: '.$_ci_file); + } + + // This allows anything loaded using $this->load (views, files, etc.) + // to become accessible from within the Controller and Model functions. + + $_ci_CI =& get_instance(); + foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var) + { + if ( ! isset($this->$_ci_key)) + { + $this->$_ci_key =& $_ci_CI->$_ci_key; + } + } + + /* + * Extract and cache variables + * + * You can either set variables using the dedicated $this->load_vars() + * function or via the second parameter of this function. We'll merge + * the two types and cache them so that views that are embedded within + * other views can have access to these variables. + */ + if (is_array($_ci_vars)) + { + $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars); + } + extract($this->_ci_cached_vars); + + /* + * Buffer the output + * + * We buffer the output for two reasons: + * 1. Speed. You get a significant speed boost. + * 2. So that the final rendered template can be + * post-processed by the output class. Why do we + * need post processing? For one thing, in order to + * show the elapsed page load time. Unless we + * can intercept the content right before it's sent to + * the browser and then stop the timer it won't be accurate. + */ + ob_start(); + + // If the PHP installation does not support short tags we'll + // do a little string replacement, changing the short tags + // to standard PHP echo statements. + + if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE) + { + echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace(' $this->_ci_ob_level + 1) + { + ob_end_flush(); + } + else + { + $_ci_CI->output->append_output(ob_get_contents()); + @ob_end_clean(); + } + } + + // -------------------------------------------------------------------- + + /** + * Load class + * + * This function loads the requested class. + * + * @param string the item that is being loaded + * @param mixed any additional parameters + * @param string an optional object name + * @return void + */ + protected function _ci_load_class($class, $params = NULL, $object_name = NULL) + { + // Get the class name, and while we're at it trim any slashes. + // The directory path can be included as part of the class name, + // but we don't want a leading slash + $class = str_replace('.php', '', trim($class, '/')); + + // Was the path included with the class name? + // We look for a slash to determine this + $subdir = ''; + if (($last_slash = strrpos($class, '/')) !== FALSE) + { + // Extract the path + $subdir = substr($class, 0, $last_slash + 1); + + // Get the filename from the path + $class = substr($class, $last_slash + 1); + } + + // We'll test for both lowercase and capitalized versions of the file name + foreach (array(ucfirst($class), strtolower($class)) as $class) + { + $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php'; + + // Is this a class extension request? + if (file_exists($subclass)) + { + $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php'; + + if ( ! file_exists($baseclass)) + { + log_message('error', "Unable to load the requested class: ".$class); + show_error("Unable to load the requested class: ".$class); + } + + // Safety: Was the class already loaded by a previous call? + if (in_array($subclass, $this->_ci_loaded_files)) + { + // Before we deem this to be a duplicate request, let's see + // if a custom object name is being supplied. If so, we'll + // return a new instance of the object + if ( ! is_null($object_name)) + { + $CI =& get_instance(); + if ( ! isset($CI->$object_name)) + { + return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name); + } + } + + $is_duplicate = TRUE; + log_message('debug', $class." class already loaded. Second attempt ignored."); + return; + } + + include_once($baseclass); + include_once($subclass); + $this->_ci_loaded_files[] = $subclass; + + return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name); + } + + // Lets search for the requested library file and load it. + $is_duplicate = FALSE; + foreach ($this->_ci_library_paths as $path) + { + $filepath = $path.'libraries/'.$subdir.$class.'.php'; + + // Does the file exist? No? Bummer... + if ( ! file_exists($filepath)) + { + continue; + } + + // Safety: Was the class already loaded by a previous call? + if (in_array($filepath, $this->_ci_loaded_files)) + { + // Before we deem this to be a duplicate request, let's see + // if a custom object name is being supplied. If so, we'll + // return a new instance of the object + if ( ! is_null($object_name)) + { + $CI =& get_instance(); + if ( ! isset($CI->$object_name)) + { + return $this->_ci_init_class($class, '', $params, $object_name); + } + } + + $is_duplicate = TRUE; + log_message('debug', $class." class already loaded. Second attempt ignored."); + return; + } + + include_once($filepath); + $this->_ci_loaded_files[] = $filepath; + return $this->_ci_init_class($class, '', $params, $object_name); + } + + } // END FOREACH + + // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified? + if ($subdir == '') + { + $path = strtolower($class).'/'.$class; + return $this->_ci_load_class($path, $params); + } + + // If we got this far we were unable to find the requested class. + // We do not issue errors if the load call failed due to a duplicate request + if ($is_duplicate == FALSE) + { + log_message('error', "Unable to load the requested class: ".$class); + show_error("Unable to load the requested class: ".$class); + } + } + + // -------------------------------------------------------------------- + + /** + * Instantiates a class + * + * @param string + * @param string + * @param bool + * @param string an optional object name + * @return null + */ + protected function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL) + { + // Is there an associated config file for this class? Note: these should always be lowercase + if ($config === NULL) + { + // Fetch the config paths containing any package paths + $config_component = $this->_ci_get_component('config'); + + if (is_array($config_component->_config_paths)) + { + // Break on the first found file, thus package files + // are not overridden by default paths + foreach ($config_component->_config_paths as $path) + { + // We test for both uppercase and lowercase, for servers that + // are case-sensitive with regard to file names. Check for environment + // first, global next + if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php')) + { + include($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'); + break; + } + elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php')) + { + include($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'); + break; + } + elseif (file_exists($path .'config/'.strtolower($class).'.php')) + { + include($path .'config/'.strtolower($class).'.php'); + break; + } + elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php')) + { + include($path .'config/'.ucfirst(strtolower($class)).'.php'); + break; + } + } + } + } + + if ($prefix == '') + { + if (class_exists('CI_'.$class)) + { + $name = 'CI_'.$class; + } + elseif (class_exists(config_item('subclass_prefix').$class)) + { + $name = config_item('subclass_prefix').$class; + } + else + { + $name = $class; + } + } + else + { + $name = $prefix.$class; + } + + // Is the class name valid? + if ( ! class_exists($name)) + { + log_message('error', "Non-existent class: ".$name); + show_error("Non-existent class: ".$class); + } + + // Set the variable name we will assign the class to + // Was a custom class name supplied? If so we'll use it + $class = strtolower($class); + + if (is_null($object_name)) + { + $classvar = ( ! isset($this->_ci_varmap[$class])) ? $class : $this->_ci_varmap[$class]; + } + else + { + $classvar = $object_name; + } + + // Save the class name and object name + $this->_ci_classes[$class] = $classvar; + + // Instantiate the class + $CI =& get_instance(); + if ($config !== NULL) + { + $CI->$classvar = new $name($config); + } + else + { + $CI->$classvar = new $name; + } + } + + // -------------------------------------------------------------------- + + /** + * Autoloader + * + * The config/autoload.php file contains an array that permits sub-systems, + * libraries, and helpers to be loaded automatically. + * + * @param array + * @return void + */ + private function _ci_autoloader() + { + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'); + } + else + { + include(APPPATH.'config/autoload.php'); + } + + if ( ! isset($autoload)) + { + return FALSE; + } + + // Autoload packages + if (isset($autoload['packages'])) + { + foreach ($autoload['packages'] as $package_path) + { + $this->add_package_path($package_path); + } + } + + // Load any custom config file + if (count($autoload['config']) > 0) + { + $CI =& get_instance(); + foreach ($autoload['config'] as $key => $val) + { + $CI->config->load($val); + } + } + + // Autoload helpers and languages + foreach (array('helper', 'language') as $type) + { + if (isset($autoload[$type]) AND count($autoload[$type]) > 0) + { + $this->$type($autoload[$type]); + } + } + + // A little tweak to remain backward compatible + // The $autoload['core'] item was deprecated + if ( ! isset($autoload['libraries']) AND isset($autoload['core'])) + { + $autoload['libraries'] = $autoload['core']; + } + + // Load libraries + if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0) + { + // Load the database driver. + if (in_array('database', $autoload['libraries'])) + { + $this->database(); + $autoload['libraries'] = array_diff($autoload['libraries'], array('database')); + } + + // Load all other libraries + foreach ($autoload['libraries'] as $item) + { + $this->library($item); + } + } + + // Autoload models + if (isset($autoload['model'])) + { + $this->model($autoload['model']); + } + } + + // -------------------------------------------------------------------- + + /** + * Object to Array + * + * Takes an object as input and converts the class variables to array key/vals + * + * @param object + * @return array + */ + protected function _ci_object_to_array($object) + { + return (is_object($object)) ? get_object_vars($object) : $object; + } + + // -------------------------------------------------------------------- + + /** + * Get a reference to a specific library or model + * + * @param string + * @return bool + */ + protected function &_ci_get_component($component) + { + $CI =& get_instance(); + return $CI->$component; + } + + // -------------------------------------------------------------------- + + /** + * Prep filename + * + * This function preps the name of various items to make loading them more reliable. + * + * @param mixed + * @param string + * @return array + */ + protected function _ci_prep_filename($filename, $extension) + { + if ( ! is_array($filename)) + { + return array(strtolower(str_replace('.php', '', str_replace($extension, '', $filename)).$extension)); + } + else + { + foreach ($filename as $key => $val) + { + $filename[$key] = strtolower(str_replace('.php', '', str_replace($extension, '', $val)).$extension); + } + + return $filename; + } + } +} + +/* End of file Loader.php */ +/* Location: ./system/core/Loader.php */ \ No newline at end of file diff --git a/system/core/Model.php b/system/core/Model.php new file mode 100644 index 0000000..e15ffbe --- /dev/null +++ b/system/core/Model.php @@ -0,0 +1,57 @@ +$key; + } +} +// END Model Class + +/* End of file Model.php */ +/* Location: ./system/core/Model.php */ \ No newline at end of file diff --git a/system/core/Output.php b/system/core/Output.php new file mode 100644 index 0000000..ccecafd --- /dev/null +++ b/system/core/Output.php @@ -0,0 +1,574 @@ +_zlib_oc = @ini_get('zlib.output_compression'); + + // Get mime types for later + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) + { + include APPPATH.'config/'.ENVIRONMENT.'/mimes.php'; + } + else + { + include APPPATH.'config/mimes.php'; + } + + + $this->mime_types = $mimes; + + log_message('debug', "Output Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Get Output + * + * Returns the current output string + * + * @access public + * @return string + */ + function get_output() + { + return $this->final_output; + } + + // -------------------------------------------------------------------- + + /** + * Set Output + * + * Sets the output string + * + * @access public + * @param string + * @return void + */ + function set_output($output) + { + $this->final_output = $output; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Append Output + * + * Appends data onto the output string + * + * @access public + * @param string + * @return void + */ + function append_output($output) + { + if ($this->final_output == '') + { + $this->final_output = $output; + } + else + { + $this->final_output .= $output; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Header + * + * Lets you set a server header which will be outputted with the final display. + * + * Note: If a file is cached, headers will not be sent. We need to figure out + * how to permit header data to be saved with the cache data... + * + * @access public + * @param string + * @param bool + * @return void + */ + function set_header($header, $replace = TRUE) + { + // If zlib.output_compression is enabled it will compress the output, + // but it will not modify the content-length header to compensate for + // the reduction, causing the browser to hang waiting for more data. + // We'll just skip content-length in those cases. + + if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) == 0) + { + return; + } + + $this->headers[] = array($header, $replace); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Content Type Header + * + * @access public + * @param string extension of the file we're outputting + * @return void + */ + function set_content_type($mime_type) + { + if (strpos($mime_type, '/') === FALSE) + { + $extension = ltrim($mime_type, '.'); + + // Is this extension supported? + if (isset($this->mime_types[$extension])) + { + $mime_type =& $this->mime_types[$extension]; + + if (is_array($mime_type)) + { + $mime_type = current($mime_type); + } + } + } + + $header = 'Content-Type: '.$mime_type; + + $this->headers[] = array($header, TRUE); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set HTTP Status Header + * moved to Common procedural functions in 1.7.2 + * + * @access public + * @param int the status code + * @param string + * @return void + */ + function set_status_header($code = 200, $text = '') + { + set_status_header($code, $text); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Enable/disable Profiler + * + * @access public + * @param bool + * @return void + */ + function enable_profiler($val = TRUE) + { + $this->enable_profiler = (is_bool($val)) ? $val : TRUE; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Profiler Sections + * + * Allows override of default / config settings for Profiler section display + * + * @access public + * @param array + * @return void + */ + function set_profiler_sections($sections) + { + foreach ($sections as $section => $enable) + { + $this->_profiler_sections[$section] = ($enable !== FALSE) ? TRUE : FALSE; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Cache + * + * @access public + * @param integer + * @return void + */ + function cache($time) + { + $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Display Output + * + * All "view" data is automatically put into this variable by the controller class: + * + * $this->final_output + * + * This function sends the finalized output data to the browser along + * with any server headers and profile data. It also stops the + * benchmark timer so the page rendering speed and memory usage can be shown. + * + * @access public + * @param string + * @return mixed + */ + function _display($output = '') + { + // Note: We use globals because we can't use $CI =& get_instance() + // since this function is sometimes called by the caching mechanism, + // which happens before the CI super object is available. + global $BM, $CFG; + + // Grab the super object if we can. + if (class_exists('CI_Controller')) + { + $CI =& get_instance(); + } + + // -------------------------------------------------------------------- + + // Set the output data + if ($output == '') + { + $output =& $this->final_output; + } + + // -------------------------------------------------------------------- + + // Do we need to write a cache file? Only if the controller does not have its + // own _output() method and we are not dealing with a cache file, which we + // can determine by the existence of the $CI object above + if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output')) + { + $this->_write_cache($output); + } + + // -------------------------------------------------------------------- + + // Parse out the elapsed time and memory usage, + // then swap the pseudo-variables with the data + + $elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end'); + + if ($this->parse_exec_vars === TRUE) + { + $memory = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB'; + + $output = str_replace('{elapsed_time}', $elapsed, $output); + $output = str_replace('{memory_usage}', $memory, $output); + } + + // -------------------------------------------------------------------- + + // Is compression requested? + if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc == FALSE) + { + if (extension_loaded('zlib')) + { + if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) AND strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) + { + ob_start('ob_gzhandler'); + } + } + } + + // -------------------------------------------------------------------- + + // Are there any server headers to send? + if (count($this->headers) > 0) + { + foreach ($this->headers as $header) + { + @header($header[0], $header[1]); + } + } + + // -------------------------------------------------------------------- + + // Does the $CI object exist? + // If not we know we are dealing with a cache file so we'll + // simply echo out the data and exit. + if ( ! isset($CI)) + { + echo $output; + log_message('debug', "Final output sent to browser"); + log_message('debug', "Total execution time: ".$elapsed); + return TRUE; + } + + // -------------------------------------------------------------------- + + // Do we need to generate profile data? + // If so, load the Profile class and run it. + if ($this->enable_profiler == TRUE) + { + $CI->load->library('profiler'); + + if ( ! empty($this->_profiler_sections)) + { + $CI->profiler->set_sections($this->_profiler_sections); + } + + // If the output data contains closing and tags + // we will remove them and add them back after we insert the profile data + if (preg_match("|.*?|is", $output)) + { + $output = preg_replace("|.*?|is", '', $output); + $output .= $CI->profiler->run(); + $output .= ''; + } + else + { + $output .= $CI->profiler->run(); + } + } + + // -------------------------------------------------------------------- + + // Does the controller contain a function named _output()? + // If so send the output there. Otherwise, echo it. + if (method_exists($CI, '_output')) + { + $CI->_output($output); + } + else + { + echo $output; // Send it to the browser! + } + + log_message('debug', "Final output sent to browser"); + log_message('debug', "Total execution time: ".$elapsed); + } + + // -------------------------------------------------------------------- + + /** + * Write a Cache File + * + * @access public + * @param string + * @return void + */ + function _write_cache($output) + { + $CI =& get_instance(); + $path = $CI->config->item('cache_path'); + + $cache_path = ($path == '') ? APPPATH.'cache/' : $path; + + if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path)) + { + log_message('error', "Unable to write cache file: ".$cache_path); + return; + } + + $uri = $CI->config->item('base_url'). + $CI->config->item('index_page'). + $CI->uri->uri_string(); + + $cache_path .= md5($uri); + + if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE)) + { + log_message('error', "Unable to write cache file: ".$cache_path); + return; + } + + $expire = time() + ($this->cache_expiration * 60); + + if (flock($fp, LOCK_EX)) + { + fwrite($fp, $expire.'TS--->'.$output); + flock($fp, LOCK_UN); + } + else + { + log_message('error', "Unable to secure a file lock for file at: ".$cache_path); + return; + } + fclose($fp); + @chmod($cache_path, FILE_WRITE_MODE); + + log_message('debug', "Cache file written: ".$cache_path); + } + + // -------------------------------------------------------------------- + + /** + * Update/serve a cached file + * + * @access public + * @param object config class + * @param object uri class + * @return void + */ + function _display_cache(&$CFG, &$URI) + { + $cache_path = ($CFG->item('cache_path') == '') ? APPPATH.'cache/' : $CFG->item('cache_path'); + + // Build the file path. The file name is an MD5 hash of the full URI + $uri = $CFG->item('base_url'). + $CFG->item('index_page'). + $URI->uri_string; + + $filepath = $cache_path.md5($uri); + + if ( ! @file_exists($filepath)) + { + return FALSE; + } + + if ( ! $fp = @fopen($filepath, FOPEN_READ)) + { + return FALSE; + } + + flock($fp, LOCK_SH); + + $cache = ''; + if (filesize($filepath) > 0) + { + $cache = fread($fp, filesize($filepath)); + } + + flock($fp, LOCK_UN); + fclose($fp); + + // Strip out the embedded timestamp + if ( ! preg_match("/(\d+TS--->)/", $cache, $match)) + { + return FALSE; + } + + // Has the file expired? If so we'll delete it. + if (time() >= trim(str_replace('TS--->', '', $match['1']))) + { + if (is_really_writable($cache_path)) + { + @unlink($filepath); + log_message('debug', "Cache file has expired. File deleted"); + return FALSE; + } + } + + // Display the cache + $this->_display(str_replace($match['0'], '', $cache)); + log_message('debug', "Cache file is current. Sending it to browser."); + return TRUE; + } + + +} +// END Output Class + +/* End of file Output.php */ +/* Location: ./system/core/Output.php */ \ No newline at end of file diff --git a/system/core/Router.php b/system/core/Router.php new file mode 100644 index 0000000..6da6674 --- /dev/null +++ b/system/core/Router.php @@ -0,0 +1,522 @@ +config =& load_class('Config', 'core'); + $this->uri =& load_class('URI', 'core'); + log_message('debug', "Router Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Set the route mapping + * + * This function determines what should be served based on the URI request, + * as well as any "routes" that have been set in the routing config file. + * + * @access private + * @return void + */ + function _set_routing() + { + // Are query strings enabled in the config file? Normally CI doesn't utilize query strings + // since URI segments are more search-engine friendly, but they can optionally be used. + // If this feature is enabled, we will gather the directory/class/method a little differently + $segments = array(); + if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')])) + { + if (isset($_GET[$this->config->item('directory_trigger')])) + { + $this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')]))); + $segments[] = $this->fetch_directory(); + } + + if (isset($_GET[$this->config->item('controller_trigger')])) + { + $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')]))); + $segments[] = $this->fetch_class(); + } + + if (isset($_GET[$this->config->item('function_trigger')])) + { + $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')]))); + $segments[] = $this->fetch_method(); + } + } + + // Load the routes.php file. + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/routes.php'); + } + elseif (is_file(APPPATH.'config/routes.php')) + { + include(APPPATH.'config/routes.php'); + } + + $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route; + unset($route); + + // Set the default controller so we can display it in the event + // the URI doesn't correlated to a valid controller. + $this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']); + + // Were there any query string segments? If so, we'll validate them and bail out since we're done. + if (count($segments) > 0) + { + return $this->_validate_request($segments); + } + + // Fetch the complete URI string + $this->uri->_fetch_uri_string(); + + // Is there a URI string? If not, the default controller specified in the "routes" file will be shown. + if ($this->uri->uri_string == '') + { + return $this->_set_default_controller(); + } + + // Do we need to remove the URL suffix? + $this->uri->_remove_url_suffix(); + + // Compile the segments into an array + $this->uri->_explode_segments(); + + // Parse any custom routing that may exist + $this->_parse_routes(); + + // Re-index the segment array so that it starts with 1 rather than 0 + $this->uri->_reindex_segments(); + } + + // -------------------------------------------------------------------- + + /** + * Set the default controller + * + * @access private + * @return void + */ + function _set_default_controller() + { + if ($this->default_controller === FALSE) + { + show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file."); + } + // Is the method being specified? + if (strpos($this->default_controller, '/') !== FALSE) + { + $x = explode('/', $this->default_controller); + + $this->set_class($x[0]); + $this->set_method($x[1]); + $this->_set_request($x); + } + else + { + $this->set_class($this->default_controller); + $this->set_method('index'); + $this->_set_request(array($this->default_controller, 'index')); + } + + // re-index the routed segments array so it starts with 1 rather than 0 + $this->uri->_reindex_segments(); + + log_message('debug', "No URI present. Default controller set."); + } + + // -------------------------------------------------------------------- + + /** + * Set the Route + * + * This function takes an array of URI segments as + * input, and sets the current class/method + * + * @access private + * @param array + * @param bool + * @return void + */ + function _set_request($segments = array()) + { + $segments = $this->_validate_request($segments); + + if (count($segments) == 0) + { + return $this->_set_default_controller(); + } + + $this->set_class($segments[0]); + + if (isset($segments[1])) + { + // A standard method request + $this->set_method($segments[1]); + } + else + { + // This lets the "routed" segment array identify that the default + // index method is being used. + $segments[1] = 'index'; + } + + // Update our "routed" segment array to contain the segments. + // Note: If there is no custom routing, this array will be + // identical to $this->uri->segments + $this->uri->rsegments = $segments; + } + + // -------------------------------------------------------------------- + + /** + * Validates the supplied segments. Attempts to determine the path to + * the controller. + * + * @access private + * @param array + * @return array + */ + function _validate_request($segments) + { + if (count($segments) == 0) + { + return $segments; + } + + // Does the requested controller exist in the root folder? + if (file_exists(APPPATH.'controllers/'.$segments[0].'.php')) + { + return $segments; + } + + // Is the controller in a sub-folder? + if (is_dir(APPPATH.'controllers/'.$segments[0])) + { + // Set the directory and remove it from the segment array + $this->set_directory($segments[0]); + $segments = array_slice($segments, 1); + + if (count($segments) > 0) + { + // Does the requested controller exist in the sub-folder? + if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) + { + if ( ! empty($this->routes['404_override'])) + { + $x = explode('/', $this->routes['404_override']); + + $this->set_directory(''); + $this->set_class($x[0]); + $this->set_method(isset($x[1]) ? $x[1] : 'index'); + + return $x; + } + else + { + show_404($this->fetch_directory().$segments[0]); + } + } + } + else + { + // Is the method being specified in the route? + if (strpos($this->default_controller, '/') !== FALSE) + { + $x = explode('/', $this->default_controller); + + $this->set_class($x[0]); + $this->set_method($x[1]); + } + else + { + $this->set_class($this->default_controller); + $this->set_method('index'); + } + + // Does the default controller exist in the sub-folder? + if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) + { + $this->directory = ''; + return array(); + } + + } + + return $segments; + } + + + // If we've gotten this far it means that the URI does not correlate to a valid + // controller class. We will now see if there is an override + if ( ! empty($this->routes['404_override'])) + { + $x = explode('/', $this->routes['404_override']); + + $this->set_class($x[0]); + $this->set_method(isset($x[1]) ? $x[1] : 'index'); + + return $x; + } + + + // Nothing else to do at this point but show a 404 + show_404($segments[0]); + } + + // -------------------------------------------------------------------- + + /** + * Parse Routes + * + * This function matches any routes that may exist in + * the config/routes.php file against the URI to + * determine if the class/method need to be remapped. + * + * @access private + * @return void + */ + function _parse_routes() + { + // Turn the segment array into a URI string + $uri = implode('/', $this->uri->segments); + + // Is there a literal match? If so we're done + if (isset($this->routes[$uri])) + { + return $this->_set_request(explode('/', $this->routes[$uri])); + } + + // Loop through the route array looking for wild-cards + foreach ($this->routes as $key => $val) + { + // Convert wild-cards to RegEx + $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key)); + + // Does the RegEx match? + if (preg_match('#^'.$key.'$#', $uri)) + { + // Do we have a back-reference? + if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE) + { + $val = preg_replace('#^'.$key.'$#', $val, $uri); + } + + return $this->_set_request(explode('/', $val)); + } + } + + // If we got this far it means we didn't encounter a + // matching route so we'll set the site default route + $this->_set_request($this->uri->segments); + } + + // -------------------------------------------------------------------- + + /** + * Set the class name + * + * @access public + * @param string + * @return void + */ + function set_class($class) + { + $this->class = str_replace(array('/', '.'), '', $class); + } + + // -------------------------------------------------------------------- + + /** + * Fetch the current class + * + * @access public + * @return string + */ + function fetch_class() + { + return $this->class; + } + + // -------------------------------------------------------------------- + + /** + * Set the method name + * + * @access public + * @param string + * @return void + */ + function set_method($method) + { + $this->method = $method; + } + + // -------------------------------------------------------------------- + + /** + * Fetch the current method + * + * @access public + * @return string + */ + function fetch_method() + { + if ($this->method == $this->fetch_class()) + { + return 'index'; + } + + return $this->method; + } + + // -------------------------------------------------------------------- + + /** + * Set the directory name + * + * @access public + * @param string + * @return void + */ + function set_directory($dir) + { + $this->directory = str_replace(array('/', '.'), '', $dir).'/'; + } + + // -------------------------------------------------------------------- + + /** + * Fetch the sub-directory (if any) that contains the requested controller class + * + * @access public + * @return string + */ + function fetch_directory() + { + return $this->directory; + } + + // -------------------------------------------------------------------- + + /** + * Set the controller overrides + * + * @access public + * @param array + * @return null + */ + function _set_overrides($routing) + { + if ( ! is_array($routing)) + { + return; + } + + if (isset($routing['directory'])) + { + $this->set_directory($routing['directory']); + } + + if (isset($routing['controller']) AND $routing['controller'] != '') + { + $this->set_class($routing['controller']); + } + + if (isset($routing['function'])) + { + $routing['function'] = ($routing['function'] == '') ? 'index' : $routing['function']; + $this->set_method($routing['function']); + } + } + + +} +// END Router Class + +/* End of file Router.php */ +/* Location: ./system/core/Router.php */ \ No newline at end of file diff --git a/system/core/Security.php b/system/core/Security.php new file mode 100644 index 0000000..00089d7 --- /dev/null +++ b/system/core/Security.php @@ -0,0 +1,876 @@ + '[removed]', + 'document.write' => '[removed]', + '.parentNode' => '[removed]', + '.innerHTML' => '[removed]', + 'window.location' => '[removed]', + '-moz-binding' => '[removed]', + '' => '-->', + ' '<![CDATA[', + '' => '<comment>' + ); + + /* never allowed, regex replacement */ + /** + * List of never allowed regex replacement + * + * @var array + * @access protected + */ + protected $_never_allowed_regex = array( + 'javascript\s*:', + 'expression\s*(\(|&\#40;)', // CSS and IE + 'vbscript\s*:', // IE, surprise! + 'Redirect\s+302', + "([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?" + ); + + /** + * Constructor + * + * @return void + */ + public function __construct() + { + // Is CSRF protection enabled? + if (config_item('csrf_protection') === TRUE) + { + // CSRF config + foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key) + { + if (FALSE !== ($val = config_item($key))) + { + $this->{'_'.$key} = $val; + } + } + + // Append application specific cookie prefix + if (config_item('cookie_prefix')) + { + $this->_csrf_cookie_name = config_item('cookie_prefix').$this->_csrf_cookie_name; + } + + // Set the CSRF hash + $this->_csrf_set_hash(); + } + + log_message('debug', "Security Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Verify Cross Site Request Forgery Protection + * + * @return object + */ + public function csrf_verify() + { + // If it's not a POST request we will set the CSRF cookie + if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') + { + return $this->csrf_set_cookie(); + } + + // Do the tokens exist in both the _POST and _COOKIE arrays? + if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])) + { + $this->csrf_show_error(); + } + + // Do the tokens match? + if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name]) + { + $this->csrf_show_error(); + } + + // We kill this since we're done and we don't want to + // polute the _POST array + unset($_POST[$this->_csrf_token_name]); + + // Nothing should last forever + unset($_COOKIE[$this->_csrf_cookie_name]); + $this->_csrf_set_hash(); + $this->csrf_set_cookie(); + + log_message('debug', 'CSRF token verified'); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Cross Site Request Forgery Protection Cookie + * + * @return object + */ + public function csrf_set_cookie() + { + $expire = time() + $this->_csrf_expire; + $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0; + + if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off')) + { + return FALSE; + } + + setcookie($this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie); + + log_message('debug', "CRSF cookie Set"); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Show CSRF Error + * + * @return void + */ + public function csrf_show_error() + { + show_error('The action you have requested is not allowed.'); + } + + // -------------------------------------------------------------------- + + /** + * Get CSRF Hash + * + * Getter Method + * + * @return string self::_csrf_hash + */ + public function get_csrf_hash() + { + return $this->_csrf_hash; + } + + // -------------------------------------------------------------------- + + /** + * Get CSRF Token Name + * + * Getter Method + * + * @return string self::csrf_token_name + */ + public function get_csrf_token_name() + { + return $this->_csrf_token_name; + } + + // -------------------------------------------------------------------- + + /** + * XSS Clean + * + * Sanitizes data so that Cross Site Scripting Hacks can be + * prevented. This function does a fair amount of work but + * it is extremely thorough, designed to prevent even the + * most obscure XSS attempts. Nothing is ever 100% foolproof, + * of course, but I haven't been able to get anything passed + * the filter. + * + * 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. + * + * This function was based in part on some code and ideas I + * got from Bitflux: http://channel.bitflux.ch/wiki/XSS_Prevention + * + * To help develop this script I used this great list of + * vulnerabilities along with a few other hacks I've + * harvested from examining vulnerabilities in other programs: + * http://ha.ckers.org/xss.html + * + * @param mixed string or array + * @param bool + * @return string + */ + public function xss_clean($str, $is_image = FALSE) + { + /* + * Is the string an array? + * + */ + if (is_array($str)) + { + while (list($key) = each($str)) + { + $str[$key] = $this->xss_clean($str[$key]); + } + + return $str; + } + + /* + * Remove Invisible Characters + */ + $str = remove_invisible_characters($str); + + // Validate Entities in URLs + $str = $this->_validate_entities($str); + + /* + * URL Decode + * + * Just in case stuff like this is submitted: + * + * Google + * + * Note: Use rawurldecode() so it does not remove plus signs + * + */ + $str = rawurldecode($str); + + /* + * Convert character entities to ASCII + * + * This permits our tests below to work reliably. + * We only convert entities that are within tags since + * these are the ones that will pose security problems. + * + */ + + $str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str); + + $str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str); + + /* + * Remove Invisible Characters Again! + */ + $str = remove_invisible_characters($str); + + /* + * Convert all tabs to spaces + * + * This prevents strings like this: ja vascript + * NOTE: we deal with spaces between characters later. + * NOTE: preg_replace was found to be amazingly slow here on + * large blocks of data, so we use str_replace. + */ + + if (strpos($str, "\t") !== FALSE) + { + $str = str_replace("\t", ' ', $str); + } + + /* + * Capture converted string for later comparison + */ + $converted_string = $str; + + // Remove Strings that are never allowed + $str = $this->_do_never_allowed($str); + + /* + * Makes PHP tags safe + * + * Note: XML tags are inadvertently replaced too: + * + * '), array('<?', '?>'), $str); + } + + /* + * Compact any exploded words + * + * This corrects words like: j a v a s c r i p t + * These words are compacted back to their correct state. + */ + $words = array( + 'javascript', 'expression', 'vbscript', 'script', 'base64', + 'applet', 'alert', 'document', 'write', 'cookie', 'window' + ); + + foreach ($words as $word) + { + $temp = ''; + + for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++) + { + $temp .= substr($word, $i, 1)."\s*"; + } + + // We only want to do this when it is followed by a non-word character + // That way valid stuff like "dealer to" does not become "dealerto" + $str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str); + } + + /* + * Remove disallowed Javascript in links or img tags + * We used to do some version comparisons and use of stripos for PHP5, + * but it is dog slow compared to these simplified non-capturing + * preg_match(), especially if the pattern exists in the string + */ + do + { + $original = $str; + + if (preg_match("/]*?)(>|$)#si", array($this, '_js_link_removal'), $str); + } + + if (preg_match("/]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str); + } + + if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str)) + { + $str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str); + } + } + while($original != $str); + + unset($original); + + // Remove evil attributes such as style, onclick and xmlns + $str = $this->_remove_evil_attributes($str, $is_image); + + /* + * Sanitize naughty HTML elements + * + * If a tag containing any of the words in the list + * below is found, the tag gets converted to entities. + * + * So this: + * Becomes: <blink> + */ + $naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss'; + $str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str); + + /* + * Sanitize naughty scripting elements + * + * Similar to above, only instead of looking for + * tags it looks for PHP and JavaScript commands + * that are disallowed. Rather than removing the + * code, it simply converts the parenthesis to entities + * rendering the code un-executable. + * + * For example: eval('some code') + * Becomes: eval('some code') + */ + $str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2(\\3)", $str); + + + // Final clean up + // This adds a bit of extra precaution in case + // something got through the above filters + $str = $this->_do_never_allowed($str); + + /* + * Images are Handled in a Special Way + * - Essentially, we want to know that after all of the character + * conversion is done whether any unwanted, likely XSS, code was found. + * If not, we return TRUE, as the image is clean. + * However, if the string post-conversion does not matched the + * string post-removal of XSS, then it fails, as there was unwanted XSS + * code found and removed/changed during processing. + */ + + if ($is_image === TRUE) + { + return ($str == $converted_string) ? TRUE: FALSE; + } + + log_message('debug', "XSS Filtering completed"); + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Random Hash for protecting URLs + * + * @return string + */ + public function xss_hash() + { + if ($this->_xss_hash == '') + { + mt_srand(); + $this->_xss_hash = md5(time() + mt_rand(0, 1999999999)); + } + + return $this->_xss_hash; + } + + // -------------------------------------------------------------------- + + /** + * HTML Entities Decode + * + * This function is a replacement for html_entity_decode() + * + * The reason we are not using html_entity_decode() by itself is because + * while it is not technically correct to leave out the semicolon + * at the end of an entity most browsers will still interpret the entity + * correctly. html_entity_decode() does not convert entities without + * semicolons, so we are left with our own little solution here. Bummer. + * + * @param string + * @param string + * @return string + */ + public function entity_decode($str, $charset='UTF-8') + { + if (stristr($str, '&') === FALSE) + { + return $str; + } + + $str = html_entity_decode($str, ENT_COMPAT, $charset); + $str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str); + return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str); + } + + // -------------------------------------------------------------------- + + /** + * Filename Security + * + * @param string + * @param bool + * @return string + */ + public function sanitize_filename($str, $relative_path = FALSE) + { + $bad = array( + "../", + "", + "<", + ">", + "'", + '"', + '&', + '$', + '#', + '{', + '}', + '[', + ']', + '=', + ';', + '?', + "%20", + "%22", + "%3c", // < + "%253c", // < + "%3e", // > + "%0e", // > + "%28", // ( + "%29", // ) + "%2528", // ( + "%26", // & + "%24", // $ + "%3f", // ? + "%3b", // ; + "%3d" // = + ); + + if ( ! $relative_path) + { + $bad[] = './'; + $bad[] = '/'; + } + + $str = remove_invisible_characters($str, FALSE); + return stripslashes(str_replace($bad, '', $str)); + } + + // ---------------------------------------------------------------- + + /** + * Compact Exploded Words + * + * Callback function for xss_clean() to remove whitespace from + * things like j a v a s c r i p t + * + * @param type + * @return type + */ + protected function _compact_exploded_words($matches) + { + return preg_replace('/\s+/s', '', $matches[1]).$matches[2]; + } + + // -------------------------------------------------------------------- + + /* + * Remove Evil HTML Attributes (like evenhandlers and style) + * + * It removes the evil attribute and either: + * - Everything up until a space + * For example, everything between the pipes: + * + * - Everything inside the quotes + * For example, everything between the pipes: + * + * + * @param string $str The string to check + * @param boolean $is_image TRUE if this is an image + * @return string The string with the evil attributes removed + */ + protected function _remove_evil_attributes($str, $is_image) + { + // All javascript event handlers (e.g. onload, onclick, onmouseover), style, and xmlns + $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction'); + + if ($is_image === TRUE) + { + /* + * Adobe Photoshop puts XML metadata into JFIF images, + * including namespacing, so we have to allow this for images. + */ + unset($evil_attributes[array_search('xmlns', $evil_attributes)]); + } + + do { + $count = 0; + $attribs = array(); + + // find occurrences of illegal attribute strings without quotes + preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER); + + foreach ($matches as $attr) + { + + $attribs[] = preg_quote($attr[0], '/'); + } + + // find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes) + preg_match_all("/(".implode('|', $evil_attributes).")\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is", $str, $matches, PREG_SET_ORDER); + + foreach ($matches as $attr) + { + $attribs[] = preg_quote($attr[0], '/'); + } + + // replace illegal attribute strings that are inside an html tag + if (count($attribs) > 0) + { + $str = preg_replace("/<(\/?[^><]+?)([^A-Za-z<>\-])(.*?)(".implode('|', $attribs).")(.*?)([\s><])([><]*)/i", '<$1 $3$5$6$7', $str, -1, $count); + } + + } while ($count); + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Sanitize Naughty HTML + * + * Callback function for xss_clean() to remove naughty HTML elements + * + * @param array + * @return string + */ + protected function _sanitize_naughty_html($matches) + { + // encode opening brace + $str = '<'.$matches[1].$matches[2].$matches[3]; + + // encode captured opening or closing brace to prevent recursive vectors + $str .= str_replace(array('>', '<'), array('>', '<'), + $matches[4]); + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * JS Link Removal + * + * Callback function for xss_clean() to sanitize links + * This limits the PCRE backtracks, making it more performance friendly + * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in + * PHP 5.2+ on link-heavy strings + * + * @param array + * @return string + */ + protected function _js_link_removal($match) + { + return str_replace( + $match[1], + preg_replace( + '#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|_filter_attributes(str_replace(array('<', '>'), '', $match[1])) + ), + $match[0] + ); + } + + // -------------------------------------------------------------------- + + /** + * JS Image Removal + * + * Callback function for xss_clean() to sanitize image tags + * This limits the PCRE backtracks, making it more performance friendly + * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in + * PHP 5.2+ on image tag heavy strings + * + * @param array + * @return string + */ + protected function _js_img_removal($match) + { + return str_replace( + $match[1], + preg_replace( + '#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|_filter_attributes(str_replace(array('<', '>'), '', $match[1])) + ), + $match[0] + ); + } + + // -------------------------------------------------------------------- + + /** + * Attribute Conversion + * + * Used as a callback for XSS Clean + * + * @param array + * @return string + */ + protected function _convert_attribute($match) + { + return str_replace(array('>', '<', '\\'), array('>', '<', '\\\\'), $match[0]); + } + + // -------------------------------------------------------------------- + + /** + * Filter Attributes + * + * Filters tag attributes for consistency and safety + * + * @param string + * @return string + */ + protected function _filter_attributes($str) + { + $out = ''; + + if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches)) + { + foreach ($matches[0] as $match) + { + $out .= preg_replace("#/\*.*?\*/#s", '', $match); + } + } + + return $out; + } + + // -------------------------------------------------------------------- + + /** + * HTML Entity Decode Callback + * + * Used as a callback for XSS Clean + * + * @param array + * @return string + */ + protected function _decode_entity($match) + { + return $this->entity_decode($match[0], strtoupper(config_item('charset'))); + } + + // -------------------------------------------------------------------- + + /** + * Validate URL entities + * + * Called by xss_clean() + * + * @param string + * @return string + */ + protected function _validate_entities($str) + { + /* + * Protect GET variables in URLs + */ + + // 901119URL5918AMP18930PROTECT8198 + + $str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str); + + /* + * Validate standard character entities + * + * Add a semicolon if missing. We do this to enable + * the conversion of entities to ASCII later. + * + */ + $str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str); + + /* + * Validate UTF16 two byte encoding (x00) + * + * Just as above, adds a semicolon if missing. + * + */ + $str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$str); + + /* + * Un-Protect GET variables in URLs + */ + $str = str_replace($this->xss_hash(), '&', $str); + + return $str; + } + + // ---------------------------------------------------------------------- + + /** + * Do Never Allowed + * + * A utility function for xss_clean() + * + * @param string + * @return string + */ + protected function _do_never_allowed($str) + { + $str = str_replace(array_keys($this->_never_allowed_str), $this->_never_allowed_str, $str); + + foreach ($this->_never_allowed_regex as $regex) + { + $str = preg_replace('#'.$regex.'#is', '[removed]', $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Set Cross Site Request Forgery Protection Cookie + * + * @return string + */ + protected function _csrf_set_hash() + { + if ($this->_csrf_hash == '') + { + // If the cookie exists we will use it's value. + // We don't necessarily want to regenerate it with + // each page load since a page could contain embedded + // sub-pages causing this feature to fail + if (isset($_COOKIE[$this->_csrf_cookie_name]) && + preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1) + { + return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; + } + + return $this->_csrf_hash = md5(uniqid(rand(), TRUE)); + } + + return $this->_csrf_hash; + } + +} + +/* End of file Security.php */ +/* Location: ./system/libraries/Security.php */ \ No newline at end of file diff --git a/system/core/URI.php b/system/core/URI.php new file mode 100644 index 0000000..a3ae20c --- /dev/null +++ b/system/core/URI.php @@ -0,0 +1,654 @@ +config =& load_class('Config', 'core'); + log_message('debug', "URI Class Initialized"); + } + + + // -------------------------------------------------------------------- + + /** + * Get the URI String + * + * @access private + * @return string + */ + function _fetch_uri_string() + { + if (strtoupper($this->config->item('uri_protocol')) == 'AUTO') + { + // Is the request coming from the command line? + if (php_sapi_name() == 'cli' or defined('STDIN')) + { + $this->_set_uri_string($this->_parse_cli_args()); + return; + } + + // Let's try the REQUEST_URI first, this will work in most situations + if ($uri = $this->_detect_uri()) + { + $this->_set_uri_string($uri); + return; + } + + // Is there a PATH_INFO variable? + // Note: some servers seem to have trouble with getenv() so we'll test it two ways + $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO'); + if (trim($path, '/') != '' && $path != "/".SELF) + { + $this->_set_uri_string($path); + return; + } + + // No PATH_INFO?... What about QUERY_STRING? + $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); + if (trim($path, '/') != '') + { + $this->_set_uri_string($path); + return; + } + + // As a last ditch effort lets try using the $_GET array + if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') + { + $this->_set_uri_string(key($_GET)); + return; + } + + // We've exhausted all our options... + $this->uri_string = ''; + return; + } + + $uri = strtoupper($this->config->item('uri_protocol')); + + if ($uri == 'REQUEST_URI') + { + $this->_set_uri_string($this->_detect_uri()); + return; + } + elseif ($uri == 'CLI') + { + $this->_set_uri_string($this->_parse_cli_args()); + return; + } + + $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri); + $this->_set_uri_string($path); + } + + // -------------------------------------------------------------------- + + /** + * Set the URI String + * + * @access public + * @param string + * @return string + */ + function _set_uri_string($str) + { + // Filter out control characters + $str = remove_invisible_characters($str, FALSE); + + // If the URI contains only a slash we'll kill it + $this->uri_string = ($str == '/') ? '' : $str; + } + + // -------------------------------------------------------------------- + + /** + * Detects the URI + * + * This function will detect the URI automatically and fix the query string + * if necessary. + * + * @access private + * @return string + */ + private function _detect_uri() + { + if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME'])) + { + return ''; + } + + $uri = $_SERVER['REQUEST_URI']; + if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0) + { + $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME'])); + } + elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0) + { + $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME']))); + } + + // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct + // URI is found, and also fixes the QUERY_STRING server var and $_GET array. + if (strncmp($uri, '?/', 2) === 0) + { + $uri = substr($uri, 2); + } + $parts = preg_split('#\?#i', $uri, 2); + $uri = $parts[0]; + if (isset($parts[1])) + { + $_SERVER['QUERY_STRING'] = $parts[1]; + parse_str($_SERVER['QUERY_STRING'], $_GET); + } + else + { + $_SERVER['QUERY_STRING'] = ''; + $_GET = array(); + } + + if ($uri == '/' || empty($uri)) + { + return '/'; + } + + $uri = parse_url($uri, PHP_URL_PATH); + + // Do some final cleaning of the URI and return it + return str_replace(array('//', '../'), '/', trim($uri, '/')); + } + + // -------------------------------------------------------------------- + + /** + * Parse cli arguments + * + * Take each command line argument and assume it is a URI segment. + * + * @access private + * @return string + */ + private function _parse_cli_args() + { + $args = array_slice($_SERVER['argv'], 1); + + return $args ? '/' . implode('/', $args) : ''; + } + + // -------------------------------------------------------------------- + + /** + * Filter segments for malicious characters + * + * @access private + * @param string + * @return string + */ + function _filter_uri($str) + { + if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE) + { + // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards + // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern + if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str)) + { + show_error('The URI you submitted has disallowed characters.', 400); + } + } + + // Convert programatic characters to entities + $bad = array('$', '(', ')', '%28', '%29'); + $good = array('$', '(', ')', '(', ')'); + + return str_replace($bad, $good, $str); + } + + // -------------------------------------------------------------------- + + /** + * Remove the suffix from the URL if needed + * + * @access private + * @return void + */ + function _remove_url_suffix() + { + if ($this->config->item('url_suffix') != "") + { + $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string); + } + } + + // -------------------------------------------------------------------- + + /** + * Explode the URI Segments. The individual segments will + * be stored in the $this->segments array. + * + * @access private + * @return void + */ + function _explode_segments() + { + foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val) + { + // Filter segments for security + $val = trim($this->_filter_uri($val)); + + if ($val != '') + { + $this->segments[] = $val; + } + } + } + + // -------------------------------------------------------------------- + /** + * Re-index Segments + * + * This function re-indexes the $this->segment array so that it + * starts at 1 rather than 0. Doing so makes it simpler to + * use functions like $this->uri->segment(n) since there is + * a 1:1 relationship between the segment array and the actual segments. + * + * @access private + * @return void + */ + function _reindex_segments() + { + array_unshift($this->segments, NULL); + array_unshift($this->rsegments, NULL); + unset($this->segments[0]); + unset($this->rsegments[0]); + } + + // -------------------------------------------------------------------- + + /** + * Fetch a URI Segment + * + * This function returns the URI segment based on the number provided. + * + * @access public + * @param integer + * @param bool + * @return string + */ + function segment($n, $no_result = FALSE) + { + return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n]; + } + + // -------------------------------------------------------------------- + + /** + * Fetch a URI "routed" Segment + * + * This function returns the re-routed URI segment (assuming routing rules are used) + * based on the number provided. If there is no routing this function returns the + * same result as $this->segment() + * + * @access public + * @param integer + * @param bool + * @return string + */ + function rsegment($n, $no_result = FALSE) + { + return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n]; + } + + // -------------------------------------------------------------------- + + /** + * Generate a key value pair from the URI string + * + * This function generates and associative array of URI data starting + * at the supplied segment. For example, if this is your URI: + * + * example.com/user/search/name/joe/location/UK/gender/male + * + * You can use this function to generate an array with this prototype: + * + * array ( + * name => joe + * location => UK + * gender => male + * ) + * + * @access public + * @param integer the starting segment number + * @param array an array of default values + * @return array + */ + function uri_to_assoc($n = 3, $default = array()) + { + return $this->_uri_to_assoc($n, $default, 'segment'); + } + /** + * Identical to above only it uses the re-routed segment array + * + * @access public + * @param integer the starting segment number + * @param array an array of default values + * @return array + * + */ + function ruri_to_assoc($n = 3, $default = array()) + { + return $this->_uri_to_assoc($n, $default, 'rsegment'); + } + + // -------------------------------------------------------------------- + + /** + * Generate a key value pair from the URI string or Re-routed URI string + * + * @access private + * @param integer the starting segment number + * @param array an array of default values + * @param string which array we should use + * @return array + */ + function _uri_to_assoc($n = 3, $default = array(), $which = 'segment') + { + if ($which == 'segment') + { + $total_segments = 'total_segments'; + $segment_array = 'segment_array'; + } + else + { + $total_segments = 'total_rsegments'; + $segment_array = 'rsegment_array'; + } + + if ( ! is_numeric($n)) + { + return $default; + } + + if (isset($this->keyval[$n])) + { + return $this->keyval[$n]; + } + + if ($this->$total_segments() < $n) + { + if (count($default) == 0) + { + return array(); + } + + $retval = array(); + foreach ($default as $val) + { + $retval[$val] = FALSE; + } + return $retval; + } + + $segments = array_slice($this->$segment_array(), ($n - 1)); + + $i = 0; + $lastval = ''; + $retval = array(); + foreach ($segments as $seg) + { + if ($i % 2) + { + $retval[$lastval] = $seg; + } + else + { + $retval[$seg] = FALSE; + $lastval = $seg; + } + + $i++; + } + + if (count($default) > 0) + { + foreach ($default as $val) + { + if ( ! array_key_exists($val, $retval)) + { + $retval[$val] = FALSE; + } + } + } + + // Cache the array for reuse + $this->keyval[$n] = $retval; + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Generate a URI string from an associative array + * + * + * @access public + * @param array an associative array of key/values + * @return array + */ + function assoc_to_uri($array) + { + $temp = array(); + foreach ((array)$array as $key => $val) + { + $temp[] = $key; + $temp[] = $val; + } + + return implode('/', $temp); + } + + // -------------------------------------------------------------------- + + /** + * Fetch a URI Segment and add a trailing slash + * + * @access public + * @param integer + * @param string + * @return string + */ + function slash_segment($n, $where = 'trailing') + { + return $this->_slash_segment($n, $where, 'segment'); + } + + // -------------------------------------------------------------------- + + /** + * Fetch a URI Segment and add a trailing slash + * + * @access public + * @param integer + * @param string + * @return string + */ + function slash_rsegment($n, $where = 'trailing') + { + return $this->_slash_segment($n, $where, 'rsegment'); + } + + // -------------------------------------------------------------------- + + /** + * Fetch a URI Segment and add a trailing slash - helper function + * + * @access private + * @param integer + * @param string + * @param string + * @return string + */ + function _slash_segment($n, $where = 'trailing', $which = 'segment') + { + $leading = '/'; + $trailing = '/'; + + if ($where == 'trailing') + { + $leading = ''; + } + elseif ($where == 'leading') + { + $trailing = ''; + } + + return $leading.$this->$which($n).$trailing; + } + + // -------------------------------------------------------------------- + + /** + * Segment Array + * + * @access public + * @return array + */ + function segment_array() + { + return $this->segments; + } + + // -------------------------------------------------------------------- + + /** + * Routed Segment Array + * + * @access public + * @return array + */ + function rsegment_array() + { + return $this->rsegments; + } + + // -------------------------------------------------------------------- + + /** + * Total number of segments + * + * @access public + * @return integer + */ + function total_segments() + { + return count($this->segments); + } + + // -------------------------------------------------------------------- + + /** + * Total number of routed segments + * + * @access public + * @return integer + */ + function total_rsegments() + { + return count($this->rsegments); + } + + // -------------------------------------------------------------------- + + /** + * Fetch the entire URI string + * + * @access public + * @return string + */ + function uri_string() + { + return $this->uri_string; + } + + + // -------------------------------------------------------------------- + + /** + * Fetch the entire Re-routed URI string + * + * @access public + * @return string + */ + function ruri_string() + { + return '/'.implode('/', $this->rsegment_array()); + } + +} +// END URI Class + +/* End of file URI.php */ +/* Location: ./system/core/URI.php */ \ No newline at end of file diff --git a/system/core/Utf8.php b/system/core/Utf8.php new file mode 100644 index 0000000..2a27d1f --- /dev/null +++ b/system/core/Utf8.php @@ -0,0 +1,165 @@ +item('charset') == 'UTF-8' // Application charset must be UTF-8 + ) + { + log_message('debug', "UTF-8 Support Enabled"); + + define('UTF8_ENABLED', TRUE); + + // set internal encoding for multibyte string functions if necessary + // and set a flag so we don't have to repeatedly use extension_loaded() + // or function_exists() + if (extension_loaded('mbstring')) + { + define('MB_ENABLED', TRUE); + mb_internal_encoding('UTF-8'); + } + else + { + define('MB_ENABLED', FALSE); + } + } + else + { + log_message('debug', "UTF-8 Support Disabled"); + define('UTF8_ENABLED', FALSE); + } + } + + // -------------------------------------------------------------------- + + /** + * Clean UTF-8 strings + * + * Ensures strings are UTF-8 + * + * @access public + * @param string + * @return string + */ + function clean_string($str) + { + if ($this->_is_ascii($str) === FALSE) + { + $str = @iconv('UTF-8', 'UTF-8//IGNORE', $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Remove ASCII control characters + * + * Removes all ASCII control characters except horizontal tabs, + * line feeds, and carriage returns, as all others can cause + * problems in XML + * + * @access public + * @param string + * @return string + */ + function safe_ascii_for_xml($str) + { + return remove_invisible_characters($str, FALSE); + } + + // -------------------------------------------------------------------- + + /** + * Convert to UTF-8 + * + * Attempts to convert a string to UTF-8 + * + * @access public + * @param string + * @param string - input encoding + * @return string + */ + function convert_to_utf8($str, $encoding) + { + if (function_exists('iconv')) + { + $str = @iconv($encoding, 'UTF-8', $str); + } + elseif (function_exists('mb_convert_encoding')) + { + $str = @mb_convert_encoding($str, 'UTF-8', $encoding); + } + else + { + return FALSE; + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Is ASCII? + * + * Tests if a string is standard 7-bit ASCII or not + * + * @access public + * @param string + * @return bool + */ + function _is_ascii($str) + { + return (preg_match('/[^\x00-\x7F]/S', $str) == 0); + } + + // -------------------------------------------------------------------- + +} +// End Utf8 Class + +/* End of file Utf8.php */ +/* Location: ./system/core/Utf8.php */ \ No newline at end of file diff --git a/system/core/index.html b/system/core/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/core/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/DB.php b/system/database/DB.php new file mode 100644 index 0000000..8314d3b --- /dev/null +++ b/system/database/DB.php @@ -0,0 +1,162 @@ + $dns['scheme'], + 'hostname' => (isset($dns['host'])) ? rawurldecode($dns['host']) : '', + 'username' => (isset($dns['user'])) ? rawurldecode($dns['user']) : '', + 'password' => (isset($dns['pass'])) ? rawurldecode($dns['pass']) : '', + 'database' => (isset($dns['path'])) ? rawurldecode(substr($dns['path'], 1)) : '' + ); + + // were additional config items set? + if (isset($dns['query'])) + { + parse_str($dns['query'], $extra); + + foreach ($extra as $key => $val) + { + // booleans please + if (strtoupper($val) == "TRUE") + { + $val = TRUE; + } + elseif (strtoupper($val) == "FALSE") + { + $val = FALSE; + } + + $params[$key] = $val; + } + } + } + + // No DB specified yet? Beat them senseless... + if ( ! isset($params['dbdriver']) OR $params['dbdriver'] == '') + { + show_error('You have not selected a database type to connect to.'); + } + + // Load the DB classes. Note: Since the active record class is optional + // we need to dynamically create a class that extends proper parent class + // based on whether we're using the active record class or not. + // Kudos to Paul for discovering this clever use of eval() + + if ($active_record_override !== NULL) + { + $active_record = $active_record_override; + } + + require_once(BASEPATH.'database/DB_driver.php'); + + if ( ! isset($active_record) OR $active_record == TRUE) + { + require_once(BASEPATH.'database/DB_active_rec.php'); + + if ( ! class_exists('CI_DB')) + { + eval('class CI_DB extends CI_DB_active_record { }'); + } + } + else + { + if ( ! class_exists('CI_DB')) + { + eval('class CI_DB extends CI_DB_driver { }'); + } + } + + require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php'); + + // Instantiate the DB adapter + $driver = 'CI_DB_'.$params['dbdriver'].'_driver'; + $DB = new $driver($params); + + if ($DB->autoinit == TRUE) + { + $DB->initialize(); + } + + if (isset($params['stricton']) && $params['stricton'] == TRUE) + { + $DB->query('SET SESSION sql_mode="STRICT_ALL_TABLES"'); + } + + return $DB; +} + + + +/* End of file DB.php */ +/* Location: ./system/database/DB.php */ \ No newline at end of file diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php new file mode 100644 index 0000000..10febb1 --- /dev/null +++ b/system/database/DB_active_rec.php @@ -0,0 +1,2045 @@ +ar_select[] = $val; + $this->ar_no_escape[] = $escape; + + if ($this->ar_caching === TRUE) + { + $this->ar_cache_select[] = $val; + $this->ar_cache_exists[] = 'select'; + $this->ar_cache_no_escape[] = $escape; + } + } + } + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Select Max + * + * Generates a SELECT MAX(field) portion of a query + * + * @param string the field + * @param string an alias + * @return object + */ + public function select_max($select = '', $alias = '') + { + return $this->_max_min_avg_sum($select, $alias, 'MAX'); + } + + // -------------------------------------------------------------------- + + /** + * Select Min + * + * Generates a SELECT MIN(field) portion of a query + * + * @param string the field + * @param string an alias + * @return object + */ + public function select_min($select = '', $alias = '') + { + return $this->_max_min_avg_sum($select, $alias, 'MIN'); + } + + // -------------------------------------------------------------------- + + /** + * Select Average + * + * Generates a SELECT AVG(field) portion of a query + * + * @param string the field + * @param string an alias + * @return object + */ + public function select_avg($select = '', $alias = '') + { + return $this->_max_min_avg_sum($select, $alias, 'AVG'); + } + + // -------------------------------------------------------------------- + + /** + * Select Sum + * + * Generates a SELECT SUM(field) portion of a query + * + * @param string the field + * @param string an alias + * @return object + */ + public function select_sum($select = '', $alias = '') + { + return $this->_max_min_avg_sum($select, $alias, 'SUM'); + } + + // -------------------------------------------------------------------- + + /** + * Processing Function for the four functions above: + * + * select_max() + * select_min() + * select_avg() + * select_sum() + * + * @param string the field + * @param string an alias + * @return object + */ + protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX') + { + if ( ! is_string($select) OR $select == '') + { + $this->display_error('db_invalid_query'); + } + + $type = strtoupper($type); + + if ( ! in_array($type, array('MAX', 'MIN', 'AVG', 'SUM'))) + { + show_error('Invalid function type: '.$type); + } + + if ($alias == '') + { + $alias = $this->_create_alias_from_table(trim($select)); + } + + $sql = $type.'('.$this->_protect_identifiers(trim($select)).') AS '.$alias; + + $this->ar_select[] = $sql; + + if ($this->ar_caching === TRUE) + { + $this->ar_cache_select[] = $sql; + $this->ar_cache_exists[] = 'select'; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Determines the alias name based on the table + * + * @param string + * @return string + */ + protected function _create_alias_from_table($item) + { + if (strpos($item, '.') !== FALSE) + { + return end(explode('.', $item)); + } + + return $item; + } + + // -------------------------------------------------------------------- + + /** + * DISTINCT + * + * Sets a flag which tells the query string compiler to add DISTINCT + * + * @param bool + * @return object + */ + public function distinct($val = TRUE) + { + $this->ar_distinct = (is_bool($val)) ? $val : TRUE; + return $this; + } + + // -------------------------------------------------------------------- + + /** + * From + * + * Generates the FROM portion of the query + * + * @param mixed can be a string or array + * @return object + */ + public function from($from) + { + foreach ((array) $from as $val) + { + if (strpos($val, ',') !== FALSE) + { + foreach (explode(',', $val) as $v) + { + $v = trim($v); + $this->_track_aliases($v); + + $this->ar_from[] = $this->_protect_identifiers($v, TRUE, NULL, FALSE); + + if ($this->ar_caching === TRUE) + { + $this->ar_cache_from[] = $this->_protect_identifiers($v, TRUE, NULL, FALSE); + $this->ar_cache_exists[] = 'from'; + } + } + + } + else + { + $val = trim($val); + + // Extract any aliases that might exist. We use this information + // in the _protect_identifiers to know whether to add a table prefix + $this->_track_aliases($val); + + $this->ar_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE); + + if ($this->ar_caching === TRUE) + { + $this->ar_cache_from[] = $this->_protect_identifiers($val, TRUE, NULL, FALSE); + $this->ar_cache_exists[] = 'from'; + } + } + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Join + * + * Generates the JOIN portion of the query + * + * @param string + * @param string the join condition + * @param string the type of join + * @return object + */ + public function join($table, $cond, $type = '') + { + if ($type != '') + { + $type = strtoupper(trim($type)); + + if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'))) + { + $type = ''; + } + else + { + $type .= ' '; + } + } + + // Extract any aliases that might exist. We use this information + // in the _protect_identifiers to know whether to add a table prefix + $this->_track_aliases($table); + + // Strip apart the condition and protect the identifiers + if (preg_match('/([\w\.]+)([\W\s]+)(.+)/', $cond, $match)) + { + $match[1] = $this->_protect_identifiers($match[1]); + $match[3] = $this->_protect_identifiers($match[3]); + + $cond = $match[1].$match[2].$match[3]; + } + + // Assemble the JOIN statement + $join = $type.'JOIN '.$this->_protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond; + + $this->ar_join[] = $join; + if ($this->ar_caching === TRUE) + { + $this->ar_cache_join[] = $join; + $this->ar_cache_exists[] = 'join'; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Where + * + * Generates the WHERE portion of the query. Separates + * multiple calls with AND + * + * @param mixed + * @param mixed + * @return object + */ + public function where($key, $value = NULL, $escape = TRUE) + { + return $this->_where($key, $value, 'AND ', $escape); + } + + // -------------------------------------------------------------------- + + /** + * OR Where + * + * Generates the WHERE portion of the query. Separates + * multiple calls with OR + * + * @param mixed + * @param mixed + * @return object + */ + public function or_where($key, $value = NULL, $escape = TRUE) + { + return $this->_where($key, $value, 'OR ', $escape); + } + + // -------------------------------------------------------------------- + + /** + * Where + * + * Called by where() or or_where() + * + * @param mixed + * @param mixed + * @param string + * @return object + */ + protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) + { + if ( ! is_array($key)) + { + $key = array($key => $value); + } + + // If the escape value was not set will will base it on the global setting + if ( ! is_bool($escape)) + { + $escape = $this->_protect_identifiers; + } + + foreach ($key as $k => $v) + { + $prefix = (count($this->ar_where) == 0 AND count($this->ar_cache_where) == 0) ? '' : $type; + + if (is_null($v) && ! $this->_has_operator($k)) + { + // value appears not to have been set, assign the test to IS NULL + $k .= ' IS NULL'; + } + + if ( ! is_null($v)) + { + if ($escape === TRUE) + { + $k = $this->_protect_identifiers($k, FALSE, $escape); + + $v = ' '.$this->escape($v); + } + + if ( ! $this->_has_operator($k)) + { + $k .= ' = '; + } + } + else + { + $k = $this->_protect_identifiers($k, FALSE, $escape); + } + + $this->ar_where[] = $prefix.$k.$v; + + if ($this->ar_caching === TRUE) + { + $this->ar_cache_where[] = $prefix.$k.$v; + $this->ar_cache_exists[] = 'where'; + } + + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Where_in + * + * Generates a WHERE field IN ('item', 'item') SQL query joined with + * AND if appropriate + * + * @param string The field to search + * @param array The values searched on + * @return object + */ + public function where_in($key = NULL, $values = NULL) + { + return $this->_where_in($key, $values); + } + + // -------------------------------------------------------------------- + + /** + * Where_in_or + * + * Generates a WHERE field IN ('item', 'item') SQL query joined with + * OR if appropriate + * + * @param string The field to search + * @param array The values searched on + * @return object + */ + public function or_where_in($key = NULL, $values = NULL) + { + return $this->_where_in($key, $values, FALSE, 'OR '); + } + + // -------------------------------------------------------------------- + + /** + * Where_not_in + * + * Generates a WHERE field NOT IN ('item', 'item') SQL query joined + * with AND if appropriate + * + * @param string The field to search + * @param array The values searched on + * @return object + */ + public function where_not_in($key = NULL, $values = NULL) + { + return $this->_where_in($key, $values, TRUE); + } + + // -------------------------------------------------------------------- + + /** + * Where_not_in_or + * + * Generates a WHERE field NOT IN ('item', 'item') SQL query joined + * with OR if appropriate + * + * @param string The field to search + * @param array The values searched on + * @return object + */ + public function or_where_not_in($key = NULL, $values = NULL) + { + return $this->_where_in($key, $values, TRUE, 'OR '); + } + + // -------------------------------------------------------------------- + + /** + * Where_in + * + * Called by where_in, where_in_or, where_not_in, where_not_in_or + * + * @param string The field to search + * @param array The values searched on + * @param boolean If the statement would be IN or NOT IN + * @param string + * @return object + */ + protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ') + { + if ($key === NULL OR $values === NULL) + { + return; + } + + if ( ! is_array($values)) + { + $values = array($values); + } + + $not = ($not) ? ' NOT' : ''; + + foreach ($values as $value) + { + $this->ar_wherein[] = $this->escape($value); + } + + $prefix = (count($this->ar_where) == 0) ? '' : $type; + + $where_in = $prefix . $this->_protect_identifiers($key) . $not . " IN (" . implode(", ", $this->ar_wherein) . ") "; + + $this->ar_where[] = $where_in; + if ($this->ar_caching === TRUE) + { + $this->ar_cache_where[] = $where_in; + $this->ar_cache_exists[] = 'where'; + } + + // reset the array for multiple calls + $this->ar_wherein = array(); + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Like + * + * Generates a %LIKE% portion of the query. Separates + * multiple calls with AND + * + * @param mixed + * @param mixed + * @return object + */ + public function like($field, $match = '', $side = 'both') + { + return $this->_like($field, $match, 'AND ', $side); + } + + // -------------------------------------------------------------------- + + /** + * Not Like + * + * Generates a NOT LIKE portion of the query. Separates + * multiple calls with AND + * + * @param mixed + * @param mixed + * @return object + */ + public function not_like($field, $match = '', $side = 'both') + { + return $this->_like($field, $match, 'AND ', $side, 'NOT'); + } + + // -------------------------------------------------------------------- + + /** + * OR Like + * + * Generates a %LIKE% portion of the query. Separates + * multiple calls with OR + * + * @param mixed + * @param mixed + * @return object + */ + public function or_like($field, $match = '', $side = 'both') + { + return $this->_like($field, $match, 'OR ', $side); + } + + // -------------------------------------------------------------------- + + /** + * OR Not Like + * + * Generates a NOT LIKE portion of the query. Separates + * multiple calls with OR + * + * @param mixed + * @param mixed + * @return object + */ + public function or_not_like($field, $match = '', $side = 'both') + { + return $this->_like($field, $match, 'OR ', $side, 'NOT'); + } + + // -------------------------------------------------------------------- + + /** + * Like + * + * Called by like() or orlike() + * + * @param mixed + * @param mixed + * @param string + * @return object + */ + protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '') + { + if ( ! is_array($field)) + { + $field = array($field => $match); + } + + foreach ($field as $k => $v) + { + $k = $this->_protect_identifiers($k); + + $prefix = (count($this->ar_like) == 0) ? '' : $type; + + $v = $this->escape_like_str($v); + + if ($side == 'none') + { + $like_statement = $prefix." $k $not LIKE '{$v}'"; + } + elseif ($side == 'before') + { + $like_statement = $prefix." $k $not LIKE '%{$v}'"; + } + elseif ($side == 'after') + { + $like_statement = $prefix." $k $not LIKE '{$v}%'"; + } + else + { + $like_statement = $prefix." $k $not LIKE '%{$v}%'"; + } + + // some platforms require an escape sequence definition for LIKE wildcards + if ($this->_like_escape_str != '') + { + $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_chr); + } + + $this->ar_like[] = $like_statement; + if ($this->ar_caching === TRUE) + { + $this->ar_cache_like[] = $like_statement; + $this->ar_cache_exists[] = 'like'; + } + + } + return $this; + } + + // -------------------------------------------------------------------- + + /** + * GROUP BY + * + * @param string + * @return object + */ + public function group_by($by) + { + if (is_string($by)) + { + $by = explode(',', $by); + } + + foreach ($by as $val) + { + $val = trim($val); + + if ($val != '') + { + $this->ar_groupby[] = $this->_protect_identifiers($val); + + if ($this->ar_caching === TRUE) + { + $this->ar_cache_groupby[] = $this->_protect_identifiers($val); + $this->ar_cache_exists[] = 'groupby'; + } + } + } + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Sets the HAVING value + * + * Separates multiple calls with AND + * + * @param string + * @param string + * @return object + */ + public function having($key, $value = '', $escape = TRUE) + { + return $this->_having($key, $value, 'AND ', $escape); + } + + // -------------------------------------------------------------------- + + /** + * Sets the OR HAVING value + * + * Separates multiple calls with OR + * + * @param string + * @param string + * @return object + */ + public function or_having($key, $value = '', $escape = TRUE) + { + return $this->_having($key, $value, 'OR ', $escape); + } + + // -------------------------------------------------------------------- + + /** + * Sets the HAVING values + * + * Called by having() or or_having() + * + * @param string + * @param string + * @return object + */ + protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE) + { + if ( ! is_array($key)) + { + $key = array($key => $value); + } + + foreach ($key as $k => $v) + { + $prefix = (count($this->ar_having) == 0) ? '' : $type; + + if ($escape === TRUE) + { + $k = $this->_protect_identifiers($k); + } + + if ( ! $this->_has_operator($k)) + { + $k .= ' = '; + } + + if ($v != '') + { + $v = ' '.$this->escape($v); + } + + $this->ar_having[] = $prefix.$k.$v; + if ($this->ar_caching === TRUE) + { + $this->ar_cache_having[] = $prefix.$k.$v; + $this->ar_cache_exists[] = 'having'; + } + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Sets the ORDER BY value + * + * @param string + * @param string direction: asc or desc + * @return object + */ + public function order_by($orderby, $direction = '') + { + if (strtolower($direction) == 'random') + { + $orderby = ''; // Random results want or don't need a field name + $direction = $this->_random_keyword; + } + elseif (trim($direction) != '') + { + $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC'; + } + + + if (strpos($orderby, ',') !== FALSE) + { + $temp = array(); + foreach (explode(',', $orderby) as $part) + { + $part = trim($part); + if ( ! in_array($part, $this->ar_aliased_tables)) + { + $part = $this->_protect_identifiers(trim($part)); + } + + $temp[] = $part; + } + + $orderby = implode(', ', $temp); + } + else if ($direction != $this->_random_keyword) + { + $orderby = $this->_protect_identifiers($orderby); + } + + $orderby_statement = $orderby.$direction; + + $this->ar_orderby[] = $orderby_statement; + if ($this->ar_caching === TRUE) + { + $this->ar_cache_orderby[] = $orderby_statement; + $this->ar_cache_exists[] = 'orderby'; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Sets the LIMIT value + * + * @param integer the limit value + * @param integer the offset value + * @return object + */ + public function limit($value, $offset = '') + { + $this->ar_limit = (int) $value; + + if ($offset != '') + { + $this->ar_offset = (int) $offset; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Sets the OFFSET value + * + * @param integer the offset value + * @return object + */ + public function offset($offset) + { + $this->ar_offset = $offset; + return $this; + } + + // -------------------------------------------------------------------- + + /** + * The "set" function. Allows key/value pairs to be set for inserting or updating + * + * @param mixed + * @param string + * @param boolean + * @return object + */ + public function set($key, $value = '', $escape = TRUE) + { + $key = $this->_object_to_array($key); + + if ( ! is_array($key)) + { + $key = array($key => $value); + } + + foreach ($key as $k => $v) + { + if ($escape === FALSE) + { + $this->ar_set[$this->_protect_identifiers($k)] = $v; + } + else + { + $this->ar_set[$this->_protect_identifiers($k, FALSE, TRUE)] = $this->escape($v); + } + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Get + * + * Compiles the select statement based on the other functions called + * and runs the query + * + * @param string the table + * @param string the limit clause + * @param string the offset clause + * @return object + */ + public function get($table = '', $limit = null, $offset = null) + { + if ($table != '') + { + $this->_track_aliases($table); + $this->from($table); + } + + if ( ! is_null($limit)) + { + $this->limit($limit, $offset); + } + + $sql = $this->_compile_select(); + + $result = $this->query($sql); + $this->_reset_select(); + return $result; + } + + /** + * "Count All Results" query + * + * Generates a platform-specific query string that counts all records + * returned by an Active Record query. + * + * @param string + * @return string + */ + public function count_all_results($table = '') + { + if ($table != '') + { + $this->_track_aliases($table); + $this->from($table); + } + + $sql = $this->_compile_select($this->_count_string . $this->_protect_identifiers('numrows')); + + $query = $this->query($sql); + $this->_reset_select(); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * Get_Where + * + * Allows the where clause, limit and offset to be added directly + * + * @param string the where clause + * @param string the limit clause + * @param string the offset clause + * @return object + */ + public function get_where($table = '', $where = null, $limit = null, $offset = null) + { + if ($table != '') + { + $this->from($table); + } + + if ( ! is_null($where)) + { + $this->where($where); + } + + if ( ! is_null($limit)) + { + $this->limit($limit, $offset); + } + + $sql = $this->_compile_select(); + + $result = $this->query($sql); + $this->_reset_select(); + return $result; + } + + // -------------------------------------------------------------------- + + /** + * Insert_Batch + * + * Compiles batch insert strings and runs the queries + * + * @param string the table to retrieve the results from + * @param array an associative array of insert values + * @return object + */ + public function insert_batch($table = '', $set = NULL) + { + if ( ! is_null($set)) + { + $this->set_insert_batch($set); + } + + if (count($this->ar_set) == 0) + { + if ($this->db_debug) + { + //No valid data array. Folds in cases where keys and values did not match up + return $this->display_error('db_must_use_set'); + } + return FALSE; + } + + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + + // Batch this baby + for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100) + { + + $sql = $this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100)); + + //echo $sql; + + $this->query($sql); + } + + $this->_reset_write(); + + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts + * + * @param mixed + * @param string + * @param boolean + * @return object + */ + public function set_insert_batch($key, $value = '', $escape = TRUE) + { + $key = $this->_object_to_array_batch($key); + + if ( ! is_array($key)) + { + $key = array($key => $value); + } + + $keys = array_keys(current($key)); + sort($keys); + + foreach ($key as $row) + { + if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0) + { + // batch function above returns an error on an empty array + $this->ar_set[] = array(); + return; + } + + ksort($row); // puts $row in the same order as our keys + + if ($escape === FALSE) + { + $this->ar_set[] = '('.implode(',', $row).')'; + } + else + { + $clean = array(); + + foreach ($row as $value) + { + $clean[] = $this->escape($value); + } + + $this->ar_set[] = '('.implode(',', $clean).')'; + } + } + + foreach ($keys as $k) + { + $this->ar_keys[] = $this->_protect_identifiers($k); + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Insert + * + * Compiles an insert string and runs the query + * + * @param string the table to insert data into + * @param array an associative array of insert values + * @return object + */ + function insert($table = '', $set = NULL) + { + if ( ! is_null($set)) + { + $this->set($set); + } + + if (count($this->ar_set) == 0) + { + if ($this->db_debug) + { + return $this->display_error('db_must_use_set'); + } + return FALSE; + } + + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + + $sql = $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set)); + + $this->_reset_write(); + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Replace + * + * Compiles an replace into string and runs the query + * + * @param string the table to replace data into + * @param array an associative array of insert values + * @return object + */ + public function replace($table = '', $set = NULL) + { + if ( ! is_null($set)) + { + $this->set($set); + } + + if (count($this->ar_set) == 0) + { + if ($this->db_debug) + { + return $this->display_error('db_must_use_set'); + } + return FALSE; + } + + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + + $sql = $this->_replace($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->ar_set), array_values($this->ar_set)); + + $this->_reset_write(); + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Update + * + * Compiles an update string and runs the query + * + * @param string the table to retrieve the results from + * @param array an associative array of update values + * @param mixed the where clause + * @return object + */ + public function update($table = '', $set = NULL, $where = NULL, $limit = NULL) + { + // Combine any cached components with the current statements + $this->_merge_cache(); + + if ( ! is_null($set)) + { + $this->set($set); + } + + if (count($this->ar_set) == 0) + { + if ($this->db_debug) + { + return $this->display_error('db_must_use_set'); + } + return FALSE; + } + + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + + if ($where != NULL) + { + $this->where($where); + } + + if ($limit != NULL) + { + $this->limit($limit); + } + + $sql = $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_set, $this->ar_where, $this->ar_orderby, $this->ar_limit); + + $this->_reset_write(); + return $this->query($sql); + } + + + // -------------------------------------------------------------------- + + /** + * Update_Batch + * + * Compiles an update string and runs the query + * + * @param string the table to retrieve the results from + * @param array an associative array of update values + * @param string the where key + * @return object + */ + public function update_batch($table = '', $set = NULL, $index = NULL) + { + // Combine any cached components with the current statements + $this->_merge_cache(); + + if (is_null($index)) + { + if ($this->db_debug) + { + return $this->display_error('db_must_use_index'); + } + + return FALSE; + } + + if ( ! is_null($set)) + { + $this->set_update_batch($set, $index); + } + + if (count($this->ar_set) == 0) + { + if ($this->db_debug) + { + return $this->display_error('db_must_use_set'); + } + + return FALSE; + } + + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + + // Batch this baby + for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100) + { + $sql = $this->_update_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->ar_set, $i, 100), $this->_protect_identifiers($index), $this->ar_where); + + $this->query($sql); + } + + $this->_reset_write(); + } + + // -------------------------------------------------------------------- + + /** + * The "set_update_batch" function. Allows key/value pairs to be set for batch updating + * + * @param array + * @param string + * @param boolean + * @return object + */ + public function set_update_batch($key, $index = '', $escape = TRUE) + { + $key = $this->_object_to_array_batch($key); + + if ( ! is_array($key)) + { + // @todo error + } + + foreach ($key as $k => $v) + { + $index_set = FALSE; + $clean = array(); + + foreach ($v as $k2 => $v2) + { + if ($k2 == $index) + { + $index_set = TRUE; + } + else + { + $not[] = $k.'-'.$v; + } + + if ($escape === FALSE) + { + $clean[$this->_protect_identifiers($k2)] = $v2; + } + else + { + $clean[$this->_protect_identifiers($k2)] = $this->escape($v2); + } + } + + if ($index_set == FALSE) + { + return $this->display_error('db_batch_missing_index'); + } + + $this->ar_set[] = $clean; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Empty Table + * + * Compiles a delete string and runs "DELETE FROM table" + * + * @param string the table to empty + * @return object + */ + public function empty_table($table = '') + { + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + else + { + $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE); + } + + $sql = $this->_delete($table); + + $this->_reset_write(); + + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Truncate + * + * Compiles a truncate string and runs the query + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @param string the table to truncate + * @return object + */ + public function truncate($table = '') + { + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + else + { + $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE); + } + + $sql = $this->_truncate($table); + + $this->_reset_write(); + + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Delete + * + * Compiles a delete string and runs the query + * + * @param mixed the table(s) to delete from. String or array + * @param mixed the where clause + * @param mixed the limit clause + * @param boolean + * @return object + */ + public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE) + { + // Combine any cached components with the current statements + $this->_merge_cache(); + + if ($table == '') + { + if ( ! isset($this->ar_from[0])) + { + if ($this->db_debug) + { + return $this->display_error('db_must_set_table'); + } + return FALSE; + } + + $table = $this->ar_from[0]; + } + elseif (is_array($table)) + { + foreach ($table as $single_table) + { + $this->delete($single_table, $where, $limit, FALSE); + } + + $this->_reset_write(); + return; + } + else + { + $table = $this->_protect_identifiers($table, TRUE, NULL, FALSE); + } + + if ($where != '') + { + $this->where($where); + } + + if ($limit != NULL) + { + $this->limit($limit); + } + + if (count($this->ar_where) == 0 && count($this->ar_wherein) == 0 && count($this->ar_like) == 0) + { + if ($this->db_debug) + { + return $this->display_error('db_del_must_use_where'); + } + + return FALSE; + } + + $sql = $this->_delete($table, $this->ar_where, $this->ar_like, $this->ar_limit); + + if ($reset_data) + { + $this->_reset_write(); + } + + return $this->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * DB Prefix + * + * Prepends a database prefix if one exists in configuration + * + * @param string the table + * @return string + */ + public function dbprefix($table = '') + { + if ($table == '') + { + $this->display_error('db_table_name_required'); + } + + return $this->dbprefix.$table; + } + + // -------------------------------------------------------------------- + + /** + * Set DB Prefix + * + * Set's the DB Prefix to something new without needing to reconnect + * + * @param string the prefix + * @return string + */ + public function set_dbprefix($prefix = '') + { + return $this->dbprefix = $prefix; + } + + // -------------------------------------------------------------------- + + /** + * Track Aliases + * + * Used to track SQL statements written with aliased tables. + * + * @param string The table to inspect + * @return string + */ + protected function _track_aliases($table) + { + if (is_array($table)) + { + foreach ($table as $t) + { + $this->_track_aliases($t); + } + return; + } + + // Does the string contain a comma? If so, we need to separate + // the string into discreet statements + if (strpos($table, ',') !== FALSE) + { + return $this->_track_aliases(explode(',', $table)); + } + + // if a table alias is used we can recognize it by a space + if (strpos($table, " ") !== FALSE) + { + // if the alias is written with the AS keyword, remove it + $table = preg_replace('/\s+AS\s+/i', ' ', $table); + + // Grab the alias + $table = trim(strrchr($table, " ")); + + // Store the alias, if it doesn't already exist + if ( ! in_array($table, $this->ar_aliased_tables)) + { + $this->ar_aliased_tables[] = $table; + } + } + } + + // -------------------------------------------------------------------- + + /** + * Compile the SELECT statement + * + * Generates a query string based on which functions were used. + * Should not be called directly. The get() function calls it. + * + * @return string + */ + protected function _compile_select($select_override = FALSE) + { + // Combine any cached components with the current statements + $this->_merge_cache(); + + // ---------------------------------------------------------------- + + // Write the "select" portion of the query + + if ($select_override !== FALSE) + { + $sql = $select_override; + } + else + { + $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT '; + + if (count($this->ar_select) == 0) + { + $sql .= '*'; + } + else + { + // Cycle through the "select" portion of the query and prep each column name. + // The reason we protect identifiers here rather then in the select() function + // is because until the user calls the from() function we don't know if there are aliases + foreach ($this->ar_select as $key => $val) + { + $no_escape = isset($this->ar_no_escape[$key]) ? $this->ar_no_escape[$key] : NULL; + $this->ar_select[$key] = $this->_protect_identifiers($val, FALSE, $no_escape); + } + + $sql .= implode(', ', $this->ar_select); + } + } + + // ---------------------------------------------------------------- + + // Write the "FROM" portion of the query + + if (count($this->ar_from) > 0) + { + $sql .= "\nFROM "; + + $sql .= $this->_from_tables($this->ar_from); + } + + // ---------------------------------------------------------------- + + // Write the "JOIN" portion of the query + + if (count($this->ar_join) > 0) + { + $sql .= "\n"; + + $sql .= implode("\n", $this->ar_join); + } + + // ---------------------------------------------------------------- + + // Write the "WHERE" portion of the query + + if (count($this->ar_where) > 0 OR count($this->ar_like) > 0) + { + $sql .= "\nWHERE "; + } + + $sql .= implode("\n", $this->ar_where); + + // ---------------------------------------------------------------- + + // Write the "LIKE" portion of the query + + if (count($this->ar_like) > 0) + { + if (count($this->ar_where) > 0) + { + $sql .= "\nAND "; + } + + $sql .= implode("\n", $this->ar_like); + } + + // ---------------------------------------------------------------- + + // Write the "GROUP BY" portion of the query + + if (count($this->ar_groupby) > 0) + { + $sql .= "\nGROUP BY "; + + $sql .= implode(', ', $this->ar_groupby); + } + + // ---------------------------------------------------------------- + + // Write the "HAVING" portion of the query + + if (count($this->ar_having) > 0) + { + $sql .= "\nHAVING "; + $sql .= implode("\n", $this->ar_having); + } + + // ---------------------------------------------------------------- + + // Write the "ORDER BY" portion of the query + + if (count($this->ar_orderby) > 0) + { + $sql .= "\nORDER BY "; + $sql .= implode(', ', $this->ar_orderby); + + if ($this->ar_order !== FALSE) + { + $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC'; + } + } + + // ---------------------------------------------------------------- + + // Write the "LIMIT" portion of the query + + if (is_numeric($this->ar_limit)) + { + $sql .= "\n"; + $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Object to Array + * + * Takes an object as input and converts the class variables to array key/vals + * + * @param object + * @return array + */ + public function _object_to_array($object) + { + if ( ! is_object($object)) + { + return $object; + } + + $array = array(); + foreach (get_object_vars($object) as $key => $val) + { + // There are some built in keys we need to ignore for this conversion + if ( ! is_object($val) && ! is_array($val) && $key != '_parent_name') + { + $array[$key] = $val; + } + } + + return $array; + } + + // -------------------------------------------------------------------- + + /** + * Object to Array + * + * Takes an object as input and converts the class variables to array key/vals + * + * @param object + * @return array + */ + public function _object_to_array_batch($object) + { + if ( ! is_object($object)) + { + return $object; + } + + $array = array(); + $out = get_object_vars($object); + $fields = array_keys($out); + + foreach ($fields as $val) + { + // There are some built in keys we need to ignore for this conversion + if ($val != '_parent_name') + { + + $i = 0; + foreach ($out[$val] as $data) + { + $array[$i][$val] = $data; + $i++; + } + } + } + + return $array; + } + + // -------------------------------------------------------------------- + + /** + * Start Cache + * + * Starts AR caching + * + * @return void + */ + public function start_cache() + { + $this->ar_caching = TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Stop Cache + * + * Stops AR caching + * + * @return void + */ + public function stop_cache() + { + $this->ar_caching = FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Flush Cache + * + * Empties the AR cache + * + * @access public + * @return void + */ + public function flush_cache() + { + $this->_reset_run(array( + 'ar_cache_select' => array(), + 'ar_cache_from' => array(), + 'ar_cache_join' => array(), + 'ar_cache_where' => array(), + 'ar_cache_like' => array(), + 'ar_cache_groupby' => array(), + 'ar_cache_having' => array(), + 'ar_cache_orderby' => array(), + 'ar_cache_set' => array(), + 'ar_cache_exists' => array(), + 'ar_cache_no_escape' => array() + )); + } + + // -------------------------------------------------------------------- + + /** + * Merge Cache + * + * When called, this function merges any cached AR arrays with + * locally called ones. + * + * @return void + */ + protected function _merge_cache() + { + if (count($this->ar_cache_exists) == 0) + { + return; + } + + foreach ($this->ar_cache_exists as $val) + { + $ar_variable = 'ar_'.$val; + $ar_cache_var = 'ar_cache_'.$val; + + if (count($this->$ar_cache_var) == 0) + { + continue; + } + + $this->$ar_variable = array_unique(array_merge($this->$ar_cache_var, $this->$ar_variable)); + } + + // If we are "protecting identifiers" we need to examine the "from" + // portion of the query to determine if there are any aliases + if ($this->_protect_identifiers === TRUE AND count($this->ar_cache_from) > 0) + { + $this->_track_aliases($this->ar_from); + } + + $this->ar_no_escape = $this->ar_cache_no_escape; + } + + // -------------------------------------------------------------------- + + /** + * Resets the active record values. Called by the get() function + * + * @param array An array of fields to reset + * @return void + */ + protected function _reset_run($ar_reset_items) + { + foreach ($ar_reset_items as $item => $default_value) + { + if ( ! in_array($item, $this->ar_store_array)) + { + $this->$item = $default_value; + } + } + } + + // -------------------------------------------------------------------- + + /** + * Resets the active record values. Called by the get() function + * + * @return void + */ + protected function _reset_select() + { + $ar_reset_items = array( + 'ar_select' => array(), + 'ar_from' => array(), + 'ar_join' => array(), + 'ar_where' => array(), + 'ar_like' => array(), + 'ar_groupby' => array(), + 'ar_having' => array(), + 'ar_orderby' => array(), + 'ar_wherein' => array(), + 'ar_aliased_tables' => array(), + 'ar_no_escape' => array(), + 'ar_distinct' => FALSE, + 'ar_limit' => FALSE, + 'ar_offset' => FALSE, + 'ar_order' => FALSE, + ); + + $this->_reset_run($ar_reset_items); + } + + // -------------------------------------------------------------------- + + /** + * Resets the active record "write" values. + * + * Called by the insert() update() insert_batch() update_batch() and delete() functions + * + * @return void + */ + protected function _reset_write() + { + $ar_reset_items = array( + 'ar_set' => array(), + 'ar_from' => array(), + 'ar_where' => array(), + 'ar_like' => array(), + 'ar_orderby' => array(), + 'ar_keys' => array(), + 'ar_limit' => FALSE, + 'ar_order' => FALSE + ); + + $this->_reset_run($ar_reset_items); + } +} + +/* End of file DB_active_rec.php */ +/* Location: ./system/database/DB_active_rec.php */ \ No newline at end of file diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php new file mode 100644 index 0000000..ad1c28d --- /dev/null +++ b/system/database/DB_cache.php @@ -0,0 +1,195 @@ +CI + // and load the file helper since we use it a lot + $this->CI =& get_instance(); + $this->db =& $db; + $this->CI->load->helper('file'); + } + + // -------------------------------------------------------------------- + + /** + * Set Cache Directory Path + * + * @access public + * @param string the path to the cache directory + * @return bool + */ + function check_path($path = '') + { + if ($path == '') + { + if ($this->db->cachedir == '') + { + return $this->db->cache_off(); + } + + $path = $this->db->cachedir; + } + + // Add a trailing slash to the path if needed + $path = preg_replace("/(.+?)\/*$/", "\\1/", $path); + + if ( ! is_dir($path) OR ! is_really_writable($path)) + { + // If the path is wrong we'll turn off caching + return $this->db->cache_off(); + } + + $this->db->cachedir = $path; + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Retrieve a cached query + * + * The URI being requested will become the name of the cache sub-folder. + * An MD5 hash of the SQL statement will become the cache file name + * + * @access public + * @return string + */ + function read($sql) + { + if ( ! $this->check_path()) + { + return $this->db->cache_off(); + } + + $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); + + $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); + + $filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql); + + if (FALSE === ($cachedata = read_file($filepath))) + { + return FALSE; + } + + return unserialize($cachedata); + } + + // -------------------------------------------------------------------- + + /** + * Write a query to a cache file + * + * @access public + * @return bool + */ + function write($sql, $object) + { + if ( ! $this->check_path()) + { + return $this->db->cache_off(); + } + + $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); + + $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); + + $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'; + + $filename = md5($sql); + + if ( ! @is_dir($dir_path)) + { + if ( ! @mkdir($dir_path, DIR_WRITE_MODE)) + { + return FALSE; + } + + @chmod($dir_path, DIR_WRITE_MODE); + } + + if (write_file($dir_path.$filename, serialize($object)) === FALSE) + { + return FALSE; + } + + @chmod($dir_path.$filename, FILE_WRITE_MODE); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Delete cache files within a particular directory + * + * @access public + * @return bool + */ + function delete($segment_one = '', $segment_two = '') + { + if ($segment_one == '') + { + $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); + } + + if ($segment_two == '') + { + $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); + } + + $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'; + + delete_files($dir_path, TRUE); + } + + // -------------------------------------------------------------------- + + /** + * Delete all existing cache files + * + * @access public + * @return bool + */ + function delete_all() + { + delete_files($this->db->cachedir, TRUE); + } + +} + + +/* End of file DB_cache.php */ +/* Location: ./system/database/DB_cache.php */ \ No newline at end of file diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php new file mode 100644 index 0000000..775fd33 --- /dev/null +++ b/system/database/DB_driver.php @@ -0,0 +1,1410 @@ + $val) + { + $this->$key = $val; + } + } + + log_message('debug', 'Database Driver Class Initialized'); + } + + // -------------------------------------------------------------------- + + /** + * Initialize Database Settings + * + * @access private Called by the constructor + * @param mixed + * @return void + */ + function initialize() + { + // If an existing connection resource is available + // there is no need to connect and select the database + if (is_resource($this->conn_id) OR is_object($this->conn_id)) + { + return TRUE; + } + + // ---------------------------------------------------------------- + + // Connect to the database and set the connection ID + $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect(); + + // No connection resource? Throw an error + if ( ! $this->conn_id) + { + log_message('error', 'Unable to connect to the database'); + + if ($this->db_debug) + { + $this->display_error('db_unable_to_connect'); + } + return FALSE; + } + + // ---------------------------------------------------------------- + + // Select the DB... assuming a database name is specified in the config file + if ($this->database != '') + { + if ( ! $this->db_select()) + { + log_message('error', 'Unable to select database: '.$this->database); + + if ($this->db_debug) + { + $this->display_error('db_unable_to_select', $this->database); + } + return FALSE; + } + else + { + // We've selected the DB. Now we set the character set + if ( ! $this->db_set_charset($this->char_set, $this->dbcollat)) + { + return FALSE; + } + + return TRUE; + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + if ( ! $this->_db_set_charset($this->char_set, $this->dbcollat)) + { + log_message('error', 'Unable to set database connection charset: '.$this->char_set); + + if ($this->db_debug) + { + $this->display_error('db_unable_to_set_charset', $this->char_set); + } + + return FALSE; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * The name of the platform in use (mysql, mssql, etc...) + * + * @access public + * @return string + */ + function platform() + { + return $this->dbdriver; + } + + // -------------------------------------------------------------------- + + /** + * Database Version Number. Returns a string containing the + * version of the database being used + * + * @access public + * @return string + */ + function version() + { + if (FALSE === ($sql = $this->_version())) + { + if ($this->db_debug) + { + return $this->display_error('db_unsupported_function'); + } + return FALSE; + } + + // Some DBs have functions that return the version, and don't run special + // SQL queries per se. In these instances, just return the result. + $driver_version_exceptions = array('oci8', 'sqlite', 'cubrid'); + + if (in_array($this->dbdriver, $driver_version_exceptions)) + { + return $sql; + } + else + { + $query = $this->query($sql); + return $query->row('ver'); + } + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * Accepts an SQL string as input and returns a result object upon + * successful execution of a "read" type query. Returns boolean TRUE + * upon successful execution of a "write" type query. Returns boolean + * FALSE upon failure, and if the $db_debug variable is set to TRUE + * will raise an error. + * + * @access public + * @param string An SQL query string + * @param array An array of binding data + * @return mixed + */ + function query($sql, $binds = FALSE, $return_object = TRUE) + { + if ($sql == '') + { + if ($this->db_debug) + { + log_message('error', 'Invalid query: '.$sql); + return $this->display_error('db_invalid_query'); + } + return FALSE; + } + + // Verify table prefix and replace if necessary + if ( ($this->dbprefix != '' AND $this->swap_pre != '') AND ($this->dbprefix != $this->swap_pre) ) + { + $sql = preg_replace("/(\W)".$this->swap_pre."(\S+?)/", "\\1".$this->dbprefix."\\2", $sql); + } + + // Compile binds if needed + if ($binds !== FALSE) + { + $sql = $this->compile_binds($sql, $binds); + } + + // Is query caching enabled? If the query is a "read type" + // we will load the caching class and return the previously + // cached query if it exists + if ($this->cache_on == TRUE AND stristr($sql, 'SELECT')) + { + if ($this->_cache_init()) + { + $this->load_rdriver(); + if (FALSE !== ($cache = $this->CACHE->read($sql))) + { + return $cache; + } + } + } + + // Save the query for debugging + if ($this->save_queries == TRUE) + { + $this->queries[] = $sql; + } + + // Start the Query Timer + $time_start = list($sm, $ss) = explode(' ', microtime()); + + // Run the Query + if (FALSE === ($this->result_id = $this->simple_query($sql))) + { + if ($this->save_queries == TRUE) + { + $this->query_times[] = 0; + } + + // This will trigger a rollback if transactions are being used + $this->_trans_status = FALSE; + + if ($this->db_debug) + { + // grab the error number and message now, as we might run some + // additional queries before displaying the error + $error_no = $this->_error_number(); + $error_msg = $this->_error_message(); + + // We call this function in order to roll-back queries + // if transactions are enabled. If we don't call this here + // the error message will trigger an exit, causing the + // transactions to remain in limbo. + $this->trans_complete(); + + // Log and display errors + log_message('error', 'Query error: '.$error_msg); + return $this->display_error( + array( + 'Error Number: '.$error_no, + $error_msg, + $sql + ) + ); + } + + return FALSE; + } + + // Stop and aggregate the query time results + $time_end = list($em, $es) = explode(' ', microtime()); + $this->benchmark += ($em + $es) - ($sm + $ss); + + if ($this->save_queries == TRUE) + { + $this->query_times[] = ($em + $es) - ($sm + $ss); + } + + // Increment the query counter + $this->query_count++; + + // Was the query a "write" type? + // If so we'll simply return true + if ($this->is_write_type($sql) === TRUE) + { + // If caching is enabled we'll auto-cleanup any + // existing files related to this particular URI + if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init()) + { + $this->CACHE->delete(); + } + + return TRUE; + } + + // Return TRUE if we don't need to create a result object + // Currently only the Oracle driver uses this when stored + // procedures are used + if ($return_object !== TRUE) + { + return TRUE; + } + + // Load and instantiate the result driver + + $driver = $this->load_rdriver(); + $RES = new $driver(); + $RES->conn_id = $this->conn_id; + $RES->result_id = $this->result_id; + + if ($this->dbdriver == 'oci8') + { + $RES->stmt_id = $this->stmt_id; + $RES->curs_id = NULL; + $RES->limit_used = $this->limit_used; + $this->stmt_id = FALSE; + } + + // oci8 vars must be set before calling this + $RES->num_rows = $RES->num_rows(); + + // Is query caching enabled? If so, we'll serialize the + // result object and save it to a cache file. + if ($this->cache_on == TRUE AND $this->_cache_init()) + { + // We'll create a new instance of the result object + // only without the platform specific driver since + // we can't use it with cached data (the query result + // resource ID won't be any good once we've cached the + // result object, so we'll have to compile the data + // and save it) + $CR = new CI_DB_result(); + $CR->num_rows = $RES->num_rows(); + $CR->result_object = $RES->result_object(); + $CR->result_array = $RES->result_array(); + + // Reset these since cached objects can not utilize resource IDs. + $CR->conn_id = NULL; + $CR->result_id = NULL; + + $this->CACHE->write($sql, $CR); + } + + return $RES; + } + + // -------------------------------------------------------------------- + + /** + * Load the result drivers + * + * @access public + * @return string the name of the result class + */ + function load_rdriver() + { + $driver = 'CI_DB_'.$this->dbdriver.'_result'; + + if ( ! class_exists($driver)) + { + include_once(BASEPATH.'database/DB_result.php'); + include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php'); + } + + return $driver; + } + + // -------------------------------------------------------------------- + + /** + * Simple Query + * This is a simplified version of the query() function. Internally + * we only use it when running transaction commands since they do + * not require all the features of the main query() function. + * + * @access public + * @param string the sql query + * @return mixed + */ + function simple_query($sql) + { + if ( ! $this->conn_id) + { + $this->initialize(); + } + + return $this->_execute($sql); + } + + // -------------------------------------------------------------------- + + /** + * Disable Transactions + * This permits transactions to be disabled at run-time. + * + * @access public + * @return void + */ + function trans_off() + { + $this->trans_enabled = FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Enable/disable Transaction Strict Mode + * When strict mode is enabled, if you are running multiple groups of + * transactions, if one group fails all groups will be rolled back. + * If strict mode is disabled, each group is treated autonomously, meaning + * a failure of one group will not affect any others + * + * @access public + * @return void + */ + function trans_strict($mode = TRUE) + { + $this->trans_strict = is_bool($mode) ? $mode : TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Start Transaction + * + * @access public + * @return void + */ + function trans_start($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return FALSE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + $this->_trans_depth += 1; + return; + } + + $this->trans_begin($test_mode); + } + + // -------------------------------------------------------------------- + + /** + * Complete Transaction + * + * @access public + * @return bool + */ + function trans_complete() + { + if ( ! $this->trans_enabled) + { + return FALSE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 1) + { + $this->_trans_depth -= 1; + return TRUE; + } + + // The query() function will set this flag to FALSE in the event that a query failed + if ($this->_trans_status === FALSE) + { + $this->trans_rollback(); + + // If we are NOT running in strict mode, we will reset + // the _trans_status flag so that subsequent groups of transactions + // will be permitted. + if ($this->trans_strict === FALSE) + { + $this->_trans_status = TRUE; + } + + log_message('debug', 'DB Transaction Failure'); + return FALSE; + } + + $this->trans_commit(); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Lets you retrieve the transaction flag to determine if it has failed + * + * @access public + * @return bool + */ + function trans_status() + { + return $this->_trans_status; + } + + // -------------------------------------------------------------------- + + /** + * Compile Bindings + * + * @access public + * @param string the sql statement + * @param array an array of bind data + * @return string + */ + function compile_binds($sql, $binds) + { + if (strpos($sql, $this->bind_marker) === FALSE) + { + return $sql; + } + + if ( ! is_array($binds)) + { + $binds = array($binds); + } + + // Get the sql segments around the bind markers + $segments = explode($this->bind_marker, $sql); + + // The count of bind should be 1 less then the count of segments + // If there are more bind arguments trim it down + if (count($binds) >= count($segments)) { + $binds = array_slice($binds, 0, count($segments)-1); + } + + // Construct the binded query + $result = $segments[0]; + $i = 0; + foreach ($binds as $bind) + { + $result .= $this->escape($bind); + $result .= $segments[++$i]; + } + + return $result; + } + + // -------------------------------------------------------------------- + + /** + * Determines if a query is a "write" type. + * + * @access public + * @param string An SQL query string + * @return boolean + */ + function is_write_type($sql) + { + if ( ! preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql)) + { + return FALSE; + } + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Calculate the aggregate query elapsed time + * + * @access public + * @param integer The number of decimal places + * @return integer + */ + function elapsed_time($decimals = 6) + { + return number_format($this->benchmark, $decimals); + } + + // -------------------------------------------------------------------- + + /** + * Returns the total number of queries + * + * @access public + * @return integer + */ + function total_queries() + { + return $this->query_count; + } + + // -------------------------------------------------------------------- + + /** + * Returns the last query that was executed + * + * @access public + * @return void + */ + function last_query() + { + return end($this->queries); + } + + // -------------------------------------------------------------------- + + /** + * "Smart" Escape String + * + * Escapes data based on type + * Sets boolean and null types + * + * @access public + * @param string + * @return mixed + */ + function escape($str) + { + if (is_string($str)) + { + $str = "'".$this->escape_str($str)."'"; + } + elseif (is_bool($str)) + { + $str = ($str === FALSE) ? 0 : 1; + } + elseif (is_null($str)) + { + $str = 'NULL'; + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Escape LIKE String + * + * Calls the individual driver for platform + * specific escaping for LIKE conditions + * + * @access public + * @param string + * @return mixed + */ + function escape_like_str($str) + { + return $this->escape_str($str, TRUE); + } + + // -------------------------------------------------------------------- + + /** + * Primary + * + * Retrieves the primary key. It assumes that the row in the first + * position is the primary key + * + * @access public + * @param string the table name + * @return string + */ + function primary($table = '') + { + $fields = $this->list_fields($table); + + if ( ! is_array($fields)) + { + return FALSE; + } + + return current($fields); + } + + // -------------------------------------------------------------------- + + /** + * Returns an array of table names + * + * @access public + * @return array + */ + function list_tables($constrain_by_prefix = FALSE) + { + // Is there a cached result? + if (isset($this->data_cache['table_names'])) + { + return $this->data_cache['table_names']; + } + + if (FALSE === ($sql = $this->_list_tables($constrain_by_prefix))) + { + if ($this->db_debug) + { + return $this->display_error('db_unsupported_function'); + } + return FALSE; + } + + $retval = array(); + $query = $this->query($sql); + + if ($query->num_rows() > 0) + { + foreach ($query->result_array() as $row) + { + if (isset($row['TABLE_NAME'])) + { + $retval[] = $row['TABLE_NAME']; + } + else + { + $retval[] = array_shift($row); + } + } + } + + $this->data_cache['table_names'] = $retval; + return $this->data_cache['table_names']; + } + + // -------------------------------------------------------------------- + + /** + * Determine if a particular table exists + * @access public + * @return boolean + */ + function table_exists($table_name) + { + return ( ! in_array($this->_protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables())) ? FALSE : TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Fetch MySQL Field Names + * + * @access public + * @param string the table name + * @return array + */ + function list_fields($table = '') + { + // Is there a cached result? + if (isset($this->data_cache['field_names'][$table])) + { + return $this->data_cache['field_names'][$table]; + } + + if ($table == '') + { + if ($this->db_debug) + { + return $this->display_error('db_field_param_missing'); + } + return FALSE; + } + + if (FALSE === ($sql = $this->_list_columns($table))) + { + if ($this->db_debug) + { + return $this->display_error('db_unsupported_function'); + } + return FALSE; + } + + $query = $this->query($sql); + + $retval = array(); + foreach ($query->result_array() as $row) + { + if (isset($row['COLUMN_NAME'])) + { + $retval[] = $row['COLUMN_NAME']; + } + else + { + $retval[] = current($row); + } + } + + $this->data_cache['field_names'][$table] = $retval; + return $this->data_cache['field_names'][$table]; + } + + // -------------------------------------------------------------------- + + /** + * Determine if a particular field exists + * @access public + * @param string + * @param string + * @return boolean + */ + function field_exists($field_name, $table_name) + { + return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Returns an object with field data + * + * @access public + * @param string the table name + * @return object + */ + function field_data($table = '') + { + if ($table == '') + { + if ($this->db_debug) + { + return $this->display_error('db_field_param_missing'); + } + return FALSE; + } + + $query = $this->query($this->_field_data($this->_protect_identifiers($table, TRUE, NULL, FALSE))); + + return $query->field_data(); + } + + // -------------------------------------------------------------------- + + /** + * Generate an insert string + * + * @access public + * @param string the table upon which the query will be performed + * @param array an associative array data of key/values + * @return string + */ + function insert_string($table, $data) + { + $fields = array(); + $values = array(); + + foreach ($data as $key => $val) + { + $fields[] = $this->_escape_identifiers($key); + $values[] = $this->escape($val); + } + + return $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values); + } + + // -------------------------------------------------------------------- + + /** + * Generate an update string + * + * @access public + * @param string the table upon which the query will be performed + * @param array an associative array data of key/values + * @param mixed the "where" statement + * @return string + */ + function update_string($table, $data, $where) + { + if ($where == '') + { + return false; + } + + $fields = array(); + foreach ($data as $key => $val) + { + $fields[$this->_protect_identifiers($key)] = $this->escape($val); + } + + if ( ! is_array($where)) + { + $dest = array($where); + } + else + { + $dest = array(); + foreach ($where as $key => $val) + { + $prefix = (count($dest) == 0) ? '' : ' AND '; + + if ($val !== '') + { + if ( ! $this->_has_operator($key)) + { + $key .= ' ='; + } + + $val = ' '.$this->escape($val); + } + + $dest[] = $prefix.$key.$val; + } + } + + return $this->_update($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $dest); + } + + // -------------------------------------------------------------------- + + /** + * Tests whether the string has an SQL operator + * + * @access private + * @param string + * @return bool + */ + function _has_operator($str) + { + $str = trim($str); + if ( ! preg_match("/(\s|<|>|!|=|is null|is not null)/i", $str)) + { + return FALSE; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Enables a native PHP function to be run, using a platform agnostic wrapper. + * + * @access public + * @param string the function name + * @param mixed any parameters needed by the function + * @return mixed + */ + function call_function($function) + { + $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_'; + + if (FALSE === strpos($driver, $function)) + { + $function = $driver.$function; + } + + if ( ! function_exists($function)) + { + if ($this->db_debug) + { + return $this->display_error('db_unsupported_function'); + } + return FALSE; + } + else + { + $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null; + if (is_null($args)) + { + return call_user_func($function); + } + else + { + return call_user_func_array($function, $args); + } + } + } + + // -------------------------------------------------------------------- + + /** + * Set Cache Directory Path + * + * @access public + * @param string the path to the cache directory + * @return void + */ + function cache_set_path($path = '') + { + $this->cachedir = $path; + } + + // -------------------------------------------------------------------- + + /** + * Enable Query Caching + * + * @access public + * @return void + */ + function cache_on() + { + $this->cache_on = TRUE; + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Disable Query Caching + * + * @access public + * @return void + */ + function cache_off() + { + $this->cache_on = FALSE; + return FALSE; + } + + + // -------------------------------------------------------------------- + + /** + * Delete the cache files associated with a particular URI + * + * @access public + * @return void + */ + function cache_delete($segment_one = '', $segment_two = '') + { + if ( ! $this->_cache_init()) + { + return FALSE; + } + return $this->CACHE->delete($segment_one, $segment_two); + } + + // -------------------------------------------------------------------- + + /** + * Delete All cache files + * + * @access public + * @return void + */ + function cache_delete_all() + { + if ( ! $this->_cache_init()) + { + return FALSE; + } + + return $this->CACHE->delete_all(); + } + + // -------------------------------------------------------------------- + + /** + * Initialize the Cache Class + * + * @access private + * @return void + */ + function _cache_init() + { + if (is_object($this->CACHE) AND class_exists('CI_DB_Cache')) + { + return TRUE; + } + + if ( ! class_exists('CI_DB_Cache')) + { + if ( ! @include(BASEPATH.'database/DB_cache.php')) + { + return $this->cache_off(); + } + } + + $this->CACHE = new CI_DB_Cache($this); // pass db object to support multiple db connections and returned db objects + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @return void + */ + function close() + { + if (is_resource($this->conn_id) OR is_object($this->conn_id)) + { + $this->_close($this->conn_id); + } + $this->conn_id = FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Display an error message + * + * @access public + * @param string the error message + * @param string any "swap" values + * @param boolean whether to localize the message + * @return string sends the application/error_db.php template + */ + function display_error($error = '', $swap = '', $native = FALSE) + { + $LANG =& load_class('Lang', 'core'); + $LANG->load('db'); + + $heading = $LANG->line('db_error_heading'); + + if ($native == TRUE) + { + $message = $error; + } + else + { + $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error; + } + + // Find the most likely culprit of the error by going through + // the backtrace until the source file is no longer in the + // database folder. + + $trace = debug_backtrace(); + + foreach ($trace as $call) + { + if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE) + { + // Found it - use a relative path for safety + $message[] = 'Filename: '.str_replace(array(BASEPATH, APPPATH), '', $call['file']); + $message[] = 'Line Number: '.$call['line']; + + break; + } + } + + $error =& load_class('Exceptions', 'core'); + echo $error->show_error($heading, $message, 'error_db'); + exit; + } + + // -------------------------------------------------------------------- + + /** + * Protect Identifiers + * + * This function adds backticks if appropriate based on db type + * + * @access private + * @param mixed the item to escape + * @return mixed the item with backticks + */ + function protect_identifiers($item, $prefix_single = FALSE) + { + return $this->_protect_identifiers($item, $prefix_single); + } + + // -------------------------------------------------------------------- + + /** + * Protect Identifiers + * + * This function is used extensively by the Active Record class, and by + * a couple functions in this class. + * It takes a column or table name (optionally with an alias) and inserts + * the table prefix onto it. Some logic is necessary in order to deal with + * column names that include the path. Consider a query like this: + * + * SELECT * FROM hostname.database.table.column AS c FROM hostname.database.table + * + * Or a query with aliasing: + * + * SELECT m.member_id, m.member_name FROM members AS m + * + * Since the column name can include up to four segments (host, DB, table, column) + * or also have an alias prefix, we need to do a bit of work to figure this out and + * insert the table prefix (if it exists) in the proper position, and escape only + * the correct identifiers. + * + * @access private + * @param string + * @param bool + * @param mixed + * @param bool + * @return string + */ + function _protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE) + { + if ( ! is_bool($protect_identifiers)) + { + $protect_identifiers = $this->_protect_identifiers; + } + + if (is_array($item)) + { + $escaped_array = array(); + + foreach ($item as $k => $v) + { + $escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v); + } + + return $escaped_array; + } + + // Convert tabs or multiple spaces into single spaces + $item = preg_replace('/[\t ]+/', ' ', $item); + + // If the item has an alias declaration we remove it and set it aside. + // Basically we remove everything to the right of the first space + if (strpos($item, ' ') !== FALSE) + { + $alias = strstr($item, ' '); + $item = substr($item, 0, - strlen($alias)); + } + else + { + $alias = ''; + } + + // This is basically a bug fix for queries that use MAX, MIN, etc. + // If a parenthesis is found we know that we do not need to + // escape the data or add a prefix. There's probably a more graceful + // way to deal with this, but I'm not thinking of it -- Rick + if (strpos($item, '(') !== FALSE) + { + return $item.$alias; + } + + // Break the string apart if it contains periods, then insert the table prefix + // in the correct location, assuming the period doesn't indicate that we're dealing + // with an alias. While we're at it, we will escape the components + if (strpos($item, '.') !== FALSE) + { + $parts = explode('.', $item); + + // Does the first segment of the exploded item match + // one of the aliases previously identified? If so, + // we have nothing more to do other than escape the item + if (in_array($parts[0], $this->ar_aliased_tables)) + { + if ($protect_identifiers === TRUE) + { + foreach ($parts as $key => $val) + { + if ( ! in_array($val, $this->_reserved_identifiers)) + { + $parts[$key] = $this->_escape_identifiers($val); + } + } + + $item = implode('.', $parts); + } + return $item.$alias; + } + + // Is there a table prefix defined in the config file? If not, no need to do anything + if ($this->dbprefix != '') + { + // We now add the table prefix based on some logic. + // Do we have 4 segments (hostname.database.table.column)? + // If so, we add the table prefix to the column name in the 3rd segment. + if (isset($parts[3])) + { + $i = 2; + } + // Do we have 3 segments (database.table.column)? + // If so, we add the table prefix to the column name in 2nd position + elseif (isset($parts[2])) + { + $i = 1; + } + // Do we have 2 segments (table.column)? + // If so, we add the table prefix to the column name in 1st segment + else + { + $i = 0; + } + + // This flag is set when the supplied $item does not contain a field name. + // This can happen when this function is being called from a JOIN. + if ($field_exists == FALSE) + { + $i++; + } + + // Verify table prefix and replace if necessary + if ($this->swap_pre != '' && strncmp($parts[$i], $this->swap_pre, strlen($this->swap_pre)) === 0) + { + $parts[$i] = preg_replace("/^".$this->swap_pre."(\S+?)/", $this->dbprefix."\\1", $parts[$i]); + } + + // We only add the table prefix if it does not already exist + if (substr($parts[$i], 0, strlen($this->dbprefix)) != $this->dbprefix) + { + $parts[$i] = $this->dbprefix.$parts[$i]; + } + + // Put the parts back together + $item = implode('.', $parts); + } + + if ($protect_identifiers === TRUE) + { + $item = $this->_escape_identifiers($item); + } + + return $item.$alias; + } + + // Is there a table prefix? If not, no need to insert it + if ($this->dbprefix != '') + { + // Verify table prefix and replace if necessary + if ($this->swap_pre != '' && strncmp($item, $this->swap_pre, strlen($this->swap_pre)) === 0) + { + $item = preg_replace("/^".$this->swap_pre."(\S+?)/", $this->dbprefix."\\1", $item); + } + + // Do we prefix an item with no segments? + if ($prefix_single == TRUE AND substr($item, 0, strlen($this->dbprefix)) != $this->dbprefix) + { + $item = $this->dbprefix.$item; + } + } + + if ($protect_identifiers === TRUE AND ! in_array($item, $this->_reserved_identifiers)) + { + $item = $this->_escape_identifiers($item); + } + + return $item.$alias; + } + + // -------------------------------------------------------------------- + + /** + * Dummy method that allows Active Record class to be disabled + * + * This function is used extensively by every db driver. + * + * @return void + */ + protected function _reset_select() + { + } + +} + +/* End of file DB_driver.php */ +/* Location: ./system/database/DB_driver.php */ \ No newline at end of file diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php new file mode 100644 index 0000000..6bc4041 --- /dev/null +++ b/system/database/DB_forge.php @@ -0,0 +1,382 @@ +db + $CI =& get_instance(); + $this->db =& $CI->db; + log_message('debug', "Database Forge Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Create database + * + * @access public + * @param string the database name + * @return bool + */ + function create_database($db_name) + { + $sql = $this->_create_database($db_name); + + if (is_bool($sql)) + { + return $sql; + } + + return $this->db->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Drop database + * + * @access public + * @param string the database name + * @return bool + */ + function drop_database($db_name) + { + $sql = $this->_drop_database($db_name); + + if (is_bool($sql)) + { + return $sql; + } + + return $this->db->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Add Key + * + * @access public + * @param string key + * @param string type + * @return void + */ + function add_key($key = '', $primary = FALSE) + { + if (is_array($key)) + { + foreach ($key as $one) + { + $this->add_key($one, $primary); + } + + return; + } + + if ($key == '') + { + show_error('Key information is required for that operation.'); + } + + if ($primary === TRUE) + { + $this->primary_keys[] = $key; + } + else + { + $this->keys[] = $key; + } + } + + // -------------------------------------------------------------------- + + /** + * Add Field + * + * @access public + * @param string collation + * @return void + */ + function add_field($field = '') + { + if ($field == '') + { + show_error('Field information is required.'); + } + + if (is_string($field)) + { + if ($field == 'id') + { + $this->add_field(array( + 'id' => array( + 'type' => 'INT', + 'constraint' => 9, + 'auto_increment' => TRUE + ) + )); + $this->add_key('id', TRUE); + } + else + { + if (strpos($field, ' ') === FALSE) + { + show_error('Field information is required for that operation.'); + } + + $this->fields[] = $field; + } + } + + if (is_array($field)) + { + $this->fields = array_merge($this->fields, $field); + } + + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access public + * @param string the table name + * @return bool + */ + function create_table($table = '', $if_not_exists = FALSE) + { + if ($table == '') + { + show_error('A table name is required for that operation.'); + } + + if (count($this->fields) == 0) + { + show_error('Field information is required.'); + } + + $sql = $this->_create_table($this->db->dbprefix.$table, $this->fields, $this->primary_keys, $this->keys, $if_not_exists); + + $this->_reset(); + return $this->db->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access public + * @param string the table name + * @return bool + */ + function drop_table($table_name) + { + $sql = $this->_drop_table($this->db->dbprefix.$table_name); + + if (is_bool($sql)) + { + return $sql; + } + + return $this->db->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Rename Table + * + * @access public + * @param string the old table name + * @param string the new table name + * @return bool + */ + function rename_table($table_name, $new_table_name) + { + if ($table_name == '' OR $new_table_name == '') + { + show_error('A table name is required for that operation.'); + } + + $sql = $this->_rename_table($this->db->dbprefix.$table_name, $this->db->dbprefix.$new_table_name); + return $this->db->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Column Add + * + * @access public + * @param string the table name + * @param string the column name + * @param string the column definition + * @return bool + */ + function add_column($table = '', $field = array(), $after_field = '') + { + if ($table == '') + { + show_error('A table name is required for that operation.'); + } + + // add field info into field array, but we can only do one at a time + // so we cycle through + + foreach ($field as $k => $v) + { + $this->add_field(array($k => $field[$k])); + + if (count($this->fields) == 0) + { + show_error('Field information is required.'); + } + + $sql = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->fields, $after_field); + + $this->_reset(); + + if ($this->db->query($sql) === FALSE) + { + return FALSE; + } + } + + return TRUE; + + } + + // -------------------------------------------------------------------- + + /** + * Column Drop + * + * @access public + * @param string the table name + * @param string the column name + * @return bool + */ + function drop_column($table = '', $column_name = '') + { + + if ($table == '') + { + show_error('A table name is required for that operation.'); + } + + if ($column_name == '') + { + show_error('A column name is required for that operation.'); + } + + $sql = $this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name); + + return $this->db->query($sql); + } + + // -------------------------------------------------------------------- + + /** + * Column Modify + * + * @access public + * @param string the table name + * @param string the column name + * @param string the column definition + * @return bool + */ + function modify_column($table = '', $field = array()) + { + if ($table == '') + { + show_error('A table name is required for that operation.'); + } + + // add field info into field array, but we can only do one at a time + // so we cycle through + + foreach ($field as $k => $v) + { + // If no name provided, use the current name + if ( ! isset($field[$k]['name'])) + { + $field[$k]['name'] = $k; + } + + $this->add_field(array($k => $field[$k])); + + if (count($this->fields) == 0) + { + show_error('Field information is required.'); + } + + $sql = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->fields); + + $this->_reset(); + + if ($this->db->query($sql) === FALSE) + { + return FALSE; + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Reset + * + * Resets table creation vars + * + * @access private + * @return void + */ + function _reset() + { + $this->fields = array(); + $this->keys = array(); + $this->primary_keys = array(); + } + +} + +/* End of file DB_forge.php */ +/* Location: ./system/database/DB_forge.php */ \ No newline at end of file diff --git a/system/database/DB_result.php b/system/database/DB_result.php new file mode 100644 index 0000000..48d66c8 --- /dev/null +++ b/system/database/DB_result.php @@ -0,0 +1,410 @@ +result_array(); + else if ($type == 'object') return $this->result_object(); + else return $this->custom_result_object($type); + } + + // -------------------------------------------------------------------- + + /** + * Custom query result. + * + * @param class_name A string that represents the type of object you want back + * @return array of objects + */ + public function custom_result_object($class_name) + { + if (array_key_exists($class_name, $this->custom_result_object)) + { + return $this->custom_result_object[$class_name]; + } + + if ($this->result_id === FALSE OR $this->num_rows() == 0) + { + return array(); + } + + // add the data to the object + $this->_data_seek(0); + $result_object = array(); + + while ($row = $this->_fetch_object()) + { + $object = new $class_name(); + + foreach ($row as $key => $value) + { + $object->$key = $value; + } + + $result_object[] = $object; + } + + // return the array + return $this->custom_result_object[$class_name] = $result_object; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "object" version. + * + * @access public + * @return object + */ + public function result_object() + { + if (count($this->result_object) > 0) + { + return $this->result_object; + } + + // In the event that query caching is on the result_id variable + // will return FALSE since there isn't a valid SQL resource so + // we'll simply return an empty array. + if ($this->result_id === FALSE OR $this->num_rows() == 0) + { + return array(); + } + + $this->_data_seek(0); + while ($row = $this->_fetch_object()) + { + $this->result_object[] = $row; + } + + return $this->result_object; + } + + // -------------------------------------------------------------------- + + /** + * Query result. "array" version. + * + * @access public + * @return array + */ + public function result_array() + { + if (count($this->result_array) > 0) + { + return $this->result_array; + } + + // In the event that query caching is on the result_id variable + // will return FALSE since there isn't a valid SQL resource so + // we'll simply return an empty array. + if ($this->result_id === FALSE OR $this->num_rows() == 0) + { + return array(); + } + + $this->_data_seek(0); + while ($row = $this->_fetch_assoc()) + { + $this->result_array[] = $row; + } + + return $this->result_array; + } + + // -------------------------------------------------------------------- + + /** + * Query result. Acts as a wrapper function for the following functions. + * + * @access public + * @param string + * @param string can be "object" or "array" + * @return mixed either a result object or array + */ + public function row($n = 0, $type = 'object') + { + if ( ! is_numeric($n)) + { + // We cache the row data for subsequent uses + if ( ! is_array($this->row_data)) + { + $this->row_data = $this->row_array(0); + } + + // array_key_exists() instead of isset() to allow for MySQL NULL values + if (array_key_exists($n, $this->row_data)) + { + return $this->row_data[$n]; + } + // reset the $n variable if the result was not achieved + $n = 0; + } + + if ($type == 'object') return $this->row_object($n); + else if ($type == 'array') return $this->row_array($n); + else return $this->custom_row_object($n, $type); + } + + // -------------------------------------------------------------------- + + /** + * Assigns an item into a particular column slot + * + * @access public + * @return object + */ + public function set_row($key, $value = NULL) + { + // We cache the row data for subsequent uses + if ( ! is_array($this->row_data)) + { + $this->row_data = $this->row_array(0); + } + + if (is_array($key)) + { + foreach ($key as $k => $v) + { + $this->row_data[$k] = $v; + } + + return; + } + + if ($key != '' AND ! is_null($value)) + { + $this->row_data[$key] = $value; + } + } + + // -------------------------------------------------------------------- + + /** + * Returns a single result row - custom object version + * + * @access public + * @return object + */ + public function custom_row_object($n, $type) + { + $result = $this->custom_result_object($type); + + if (count($result) == 0) + { + return $result; + } + + if ($n != $this->current_row AND isset($result[$n])) + { + $this->current_row = $n; + } + + return $result[$this->current_row]; + } + + /** + * Returns a single result row - object version + * + * @access public + * @return object + */ + public function row_object($n = 0) + { + $result = $this->result_object(); + + if (count($result) == 0) + { + return $result; + } + + if ($n != $this->current_row AND isset($result[$n])) + { + $this->current_row = $n; + } + + return $result[$this->current_row]; + } + + // -------------------------------------------------------------------- + + /** + * Returns a single result row - array version + * + * @access public + * @return array + */ + public function row_array($n = 0) + { + $result = $this->result_array(); + + if (count($result) == 0) + { + return $result; + } + + if ($n != $this->current_row AND isset($result[$n])) + { + $this->current_row = $n; + } + + return $result[$this->current_row]; + } + + + // -------------------------------------------------------------------- + + /** + * Returns the "first" row + * + * @access public + * @return object + */ + public function first_row($type = 'object') + { + $result = $this->result($type); + + if (count($result) == 0) + { + return $result; + } + return $result[0]; + } + + // -------------------------------------------------------------------- + + /** + * Returns the "last" row + * + * @access public + * @return object + */ + public function last_row($type = 'object') + { + $result = $this->result($type); + + if (count($result) == 0) + { + return $result; + } + return $result[count($result) -1]; + } + + // -------------------------------------------------------------------- + + /** + * Returns the "next" row + * + * @access public + * @return object + */ + public function next_row($type = 'object') + { + $result = $this->result($type); + + if (count($result) == 0) + { + return $result; + } + + if (isset($result[$this->current_row + 1])) + { + ++$this->current_row; + } + + return $result[$this->current_row]; + } + + // -------------------------------------------------------------------- + + /** + * Returns the "previous" row + * + * @access public + * @return object + */ + public function previous_row($type = 'object') + { + $result = $this->result($type); + + if (count($result) == 0) + { + return $result; + } + + if (isset($result[$this->current_row - 1])) + { + --$this->current_row; + } + return $result[$this->current_row]; + } + + // -------------------------------------------------------------------- + + /** + * The following functions are normally overloaded by the identically named + * methods in the platform-specific driver -- except when query caching + * is used. When caching is enabled we do not load the other driver. + * These functions are primarily here to prevent undefined function errors + * when a cached result object is in use. They are not otherwise fully + * operational due to the unavailability of the database resource IDs with + * cached results. + */ + public function num_rows() { return $this->num_rows; } + public function num_fields() { return 0; } + public function list_fields() { return array(); } + public function field_data() { return array(); } + public function free_result() { return TRUE; } + protected function _data_seek() { return TRUE; } + protected function _fetch_assoc() { return array(); } + protected function _fetch_object() { return array(); } + +} +// END DB_result class + +/* End of file DB_result.php */ +/* Location: ./system/database/DB_result.php */ diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php new file mode 100644 index 0000000..52196b7 --- /dev/null +++ b/system/database/DB_utility.php @@ -0,0 +1,414 @@ +db + $CI =& get_instance(); + $this->db =& $CI->db; + + log_message('debug', "Database Utility Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * List databases + * + * @access public + * @return bool + */ + function list_databases() + { + // Is there a cached result? + if (isset($this->data_cache['db_names'])) + { + return $this->data_cache['db_names']; + } + + $query = $this->db->query($this->_list_databases()); + $dbs = array(); + if ($query->num_rows() > 0) + { + foreach ($query->result_array() as $row) + { + $dbs[] = current($row); + } + } + + $this->data_cache['db_names'] = $dbs; + return $this->data_cache['db_names']; + } + + // -------------------------------------------------------------------- + + /** + * Determine if a particular database exists + * + * @access public + * @param string + * @return boolean + */ + function database_exists($database_name) + { + // Some databases won't have access to the list_databases() function, so + // this is intended to allow them to override with their own functions as + // defined in $driver_utility.php + if (method_exists($this, '_database_exists')) + { + return $this->_database_exists($database_name); + } + else + { + return ( ! in_array($database_name, $this->list_databases())) ? FALSE : TRUE; + } + } + + + // -------------------------------------------------------------------- + + /** + * Optimize Table + * + * @access public + * @param string the table name + * @return bool + */ + function optimize_table($table_name) + { + $sql = $this->_optimize_table($table_name); + + if (is_bool($sql)) + { + show_error('db_must_use_set'); + } + + $query = $this->db->query($sql); + $res = $query->result_array(); + + // Note: Due to a bug in current() that affects some versions + // of PHP we can not pass function call directly into it + return current($res); + } + + // -------------------------------------------------------------------- + + /** + * Optimize Database + * + * @access public + * @return array + */ + function optimize_database() + { + $result = array(); + foreach ($this->db->list_tables() as $table_name) + { + $sql = $this->_optimize_table($table_name); + + if (is_bool($sql)) + { + return $sql; + } + + $query = $this->db->query($sql); + + // Build the result array... + // Note: Due to a bug in current() that affects some versions + // of PHP we can not pass function call directly into it + $res = $query->result_array(); + $res = current($res); + $key = str_replace($this->db->database.'.', '', current($res)); + $keys = array_keys($res); + unset($res[$keys[0]]); + + $result[$key] = $res; + } + + return $result; + } + + // -------------------------------------------------------------------- + + /** + * Repair Table + * + * @access public + * @param string the table name + * @return bool + */ + function repair_table($table_name) + { + $sql = $this->_repair_table($table_name); + + if (is_bool($sql)) + { + return $sql; + } + + $query = $this->db->query($sql); + + // Note: Due to a bug in current() that affects some versions + // of PHP we can not pass function call directly into it + $res = $query->result_array(); + return current($res); + } + + // -------------------------------------------------------------------- + + /** + * Generate CSV from a query result object + * + * @access public + * @param object The query result object + * @param string The delimiter - comma by default + * @param string The newline character - \n by default + * @param string The enclosure - double quote by default + * @return string + */ + function csv_from_result($query, $delim = ",", $newline = "\n", $enclosure = '"') + { + if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) + { + show_error('You must submit a valid result object'); + } + + $out = ''; + + // First generate the headings from the table column names + foreach ($query->list_fields() as $name) + { + $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim; + } + + $out = rtrim($out); + $out .= $newline; + + // Next blast through the result array and build out the rows + foreach ($query->result_array() as $row) + { + foreach ($row as $item) + { + $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure.$delim; + } + $out = rtrim($out); + $out .= $newline; + } + + return $out; + } + + // -------------------------------------------------------------------- + + /** + * Generate XML data from a query result object + * + * @access public + * @param object The query result object + * @param array Any preferences + * @return string + */ + function xml_from_result($query, $params = array()) + { + if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) + { + show_error('You must submit a valid result object'); + } + + // Set our default values + foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val) + { + if ( ! isset($params[$key])) + { + $params[$key] = $val; + } + } + + // Create variables for convenience + extract($params); + + // Load the xml helper + $CI =& get_instance(); + $CI->load->helper('xml'); + + // Generate the result + $xml = "<{$root}>".$newline; + foreach ($query->result_array() as $row) + { + $xml .= $tab."<{$element}>".$newline; + + foreach ($row as $key => $val) + { + $xml .= $tab.$tab."<{$key}>".xml_convert($val)."".$newline; + } + $xml .= $tab."".$newline; + } + $xml .= "".$newline; + + return $xml; + } + + // -------------------------------------------------------------------- + + /** + * Database Backup + * + * @access public + * @return void + */ + function backup($params = array()) + { + // If the parameters have not been submitted as an + // array then we know that it is simply the table + // name, which is a valid short cut. + if (is_string($params)) + { + $params = array('tables' => $params); + } + + // ------------------------------------------------------ + + // Set up our default preferences + $prefs = array( + 'tables' => array(), + 'ignore' => array(), + 'filename' => '', + 'format' => 'gzip', // gzip, zip, txt + 'add_drop' => TRUE, + 'add_insert' => TRUE, + 'newline' => "\n" + ); + + // Did the user submit any preferences? If so set them.... + if (count($params) > 0) + { + foreach ($prefs as $key => $val) + { + if (isset($params[$key])) + { + $prefs[$key] = $params[$key]; + } + } + } + + // ------------------------------------------------------ + + // Are we backing up a complete database or individual tables? + // If no table names were submitted we'll fetch the entire table list + if (count($prefs['tables']) == 0) + { + $prefs['tables'] = $this->db->list_tables(); + } + + // ------------------------------------------------------ + + // Validate the format + if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE)) + { + $prefs['format'] = 'txt'; + } + + // ------------------------------------------------------ + + // Is the encoder supported? If not, we'll either issue an + // error or use plain text depending on the debug settings + if (($prefs['format'] == 'gzip' AND ! @function_exists('gzencode')) + OR ($prefs['format'] == 'zip' AND ! @function_exists('gzcompress'))) + { + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_compression'); + } + + $prefs['format'] = 'txt'; + } + + // ------------------------------------------------------ + + // Set the filename if not provided - Only needed with Zip files + if ($prefs['filename'] == '' AND $prefs['format'] == 'zip') + { + $prefs['filename'] = (count($prefs['tables']) == 1) ? $prefs['tables'] : $this->db->database; + $prefs['filename'] .= '_'.date('Y-m-d_H-i', time()); + } + + // ------------------------------------------------------ + + // Was a Gzip file requested? + if ($prefs['format'] == 'gzip') + { + return gzencode($this->_backup($prefs)); + } + + // ------------------------------------------------------ + + // Was a text file requested? + if ($prefs['format'] == 'txt') + { + return $this->_backup($prefs); + } + + // ------------------------------------------------------ + + // Was a Zip file requested? + if ($prefs['format'] == 'zip') + { + // If they included the .zip file extension we'll remove it + if (preg_match("|.+?\.zip$|", $prefs['filename'])) + { + $prefs['filename'] = str_replace('.zip', '', $prefs['filename']); + } + + // Tack on the ".sql" file extension if needed + if ( ! preg_match("|.+?\.sql$|", $prefs['filename'])) + { + $prefs['filename'] .= '.sql'; + } + + // Load the Zip class and output it + + $CI =& get_instance(); + $CI->load->library('zip'); + $CI->zip->add_data($prefs['filename'], $this->_backup($prefs)); + return $CI->zip->get_zip(); + } + + } + +} + + +/* End of file DB_utility.php */ +/* Location: ./system/database/DB_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php new file mode 100644 index 0000000..d011404 --- /dev/null +++ b/system/database/drivers/cubrid/cubrid_driver.php @@ -0,0 +1,792 @@ +port == '') + { + $this->port = self::DEFAULT_PORT; + } + + $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password); + + if ($conn) + { + // Check if a user wants to run queries in dry, i.e. run the + // queries but not commit them. + if (isset($this->auto_commit) && ! $this->auto_commit) + { + cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE); + } + else + { + cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE); + $this->auto_commit = TRUE; + } + } + + return $conn; + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * In CUBRID persistent DB connection is supported natively in CUBRID + * engine which can be configured in the CUBRID Broker configuration + * file by setting the CCI_PCONNECT parameter to ON. In that case, all + * connections established between the client application and the + * server will become persistent. This is calling the same + * @cubrid_connect function will establish persisten connection + * considering that the CCI_PCONNECT is ON. + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + return $this->db_connect(); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + if (cubrid_ping($this->conn_id) === FALSE) + { + $this->conn_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + // In CUBRID there is no need to select a database as the database + // is chosen at the connection time. + // So, to determine if the database is "selected", all we have to + // do is ping the server and return that value. + return cubrid_ping($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // In CUBRID, there is no need to set charset or collation. + // This is why returning true will allow the application continue + // its normal process. + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + // To obtain the CUBRID Server version, no need to run the SQL query. + // CUBRID PHP API provides a function to determin this value. + // This is why we also need to add 'cubrid' value to the list of + // $driver_version_exceptions array in DB_driver class in + // version() function. + return cubrid_get_server_info($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return @cubrid_query($sql, $this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + // No need to prepare + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + if (cubrid_get_autocommit($this->conn_id)) + { + cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE); + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + cubrid_commit($this->conn_id); + + if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id)) + { + cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE); + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + cubrid_rollback($this->conn_id); + + if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id)) + { + cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE); + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id)) + { + $str = cubrid_real_escape_string($str, $this->conn_id); + } + else + { + $str = addslashes($str); + } + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @cubrid_affected_rows($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id() + { + return @cubrid_insert_id($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified table + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SHOW TABLES"; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'"; + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE); + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT * FROM ".$table." LIMIT 1"; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return cubrid_error($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return cubrid_errno($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + + /** + * Replace statement + * + * Generates a platform-specific replace string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _replace($table, $keys, $values) + { + return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert_batch($table, $keys, $values) + { + return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values); + } + + // -------------------------------------------------------------------- + + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = sprintf('"%s" = %s', $key, $val); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + // -------------------------------------------------------------------- + + + /** + * Update_Batch statement + * + * Generates a platform-specific batch update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @return string + */ + function _update_batch($table, $values, $index, $where = NULL) + { + $ids = array(); + $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : ''; + + foreach ($values as $key => $val) + { + $ids[] = $val[$index]; + + foreach (array_keys($val) as $field) + { + if ($field != $index) + { + $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; + } + } + } + + $sql = "UPDATE ".$table." SET "; + $cases = ''; + + foreach ($final as $k => $v) + { + $cases .= $k.' = CASE '."\n"; + foreach ($v as $row) + { + $cases .= $row."\n"; + } + + $cases .= 'ELSE '.$k.' END, '; + } + + $sql .= substr($cases, 0, -2); + + $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; + + return $sql; + } + + // -------------------------------------------------------------------- + + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return "TRUNCATE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + if ($offset == 0) + { + $offset = ''; + } + else + { + $offset .= ", "; + } + + return $sql."LIMIT ".$offset.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @cubrid_close($conn_id); + } + +} + + +/* End of file cubrid_driver.php */ +/* Location: ./system/database/drivers/cubrid/cubrid_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php new file mode 100644 index 0000000..bab03f7 --- /dev/null +++ b/system/database/drivers/cubrid/cubrid_forge.php @@ -0,0 +1,288 @@ +$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t\"" . $this->db->_protect_identifiers($field) . "\""; + + if (array_key_exists('NAME', $attributes)) + { + $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' '; + } + + if (array_key_exists('TYPE', $attributes)) + { + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + switch ($attributes['TYPE']) + { + case 'decimal': + case 'float': + case 'numeric': + $sql .= '('.implode(',', $attributes['CONSTRAINT']).')'; + break; + case 'enum': // As of version 8.4.0 CUBRID does not support + // enum data type. + break; + case 'set': + $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")'; + break; + default: + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + } + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + //$sql .= ' UNSIGNED'; + // As of version 8.4.0 CUBRID does not support UNSIGNED INTEGER data type. + // Will be supported in the next release as a part of MySQL Compatibility. + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + + if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE) + { + $sql .= ' UNIQUE'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param mixed the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + //$sql .= 'IF NOT EXISTS '; + // As of version 8.4.0 CUBRID does not support this SQL syntax. + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + + $sql .= $this->_process_fields($fields); + + // If there is a PK defined + if (count($primary_keys) > 0) + { + $key_name = "pk_" . $table . "_" . + $this->db->_protect_identifiers(implode('_', $primary_keys)); + + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tCONSTRAINT " . $key_name . " PRIMARY KEY(" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key_name = $this->db->_protect_identifiers(implode('_', $key)); + $key = $this->db->_protect_identifiers($key); + } + else + { + $key_name = $this->db->_protect_identifiers($key); + $key = array($key_name); + } + + $sql .= ",\n\tKEY \"{$key_name}\" (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n);"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return string + */ + function _drop_table($table) + { + return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param array fields + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $fields, $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type "; + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql.$this->db->_protect_identifiers($fields); + } + + $sql .= $this->_process_fields($fields); + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'RENAME TABLE '.$this->db->_protect_identifiers($table_name)." AS ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + +} + +/* End of file cubrid_forge.php */ +/* Location: ./system/database/drivers/cubrid/cubrid_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php new file mode 100644 index 0000000..6f0c2b5 --- /dev/null +++ b/system/database/drivers/cubrid/cubrid_result.php @@ -0,0 +1,202 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @cubrid_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + return cubrid_column_names($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + + $tablePrimaryKeys = array(); + + while ($field = cubrid_fetch_field($this->result_id)) + { + $F = new stdClass(); + $F->name = $field->name; + $F->type = $field->type; + $F->default = $field->def; + $F->max_length = $field->max_length; + + // At this moment primary_key property is not returned when + // cubrid_fetch_field is called. The following code will + // provide a patch for it. primary_key property will be added + // in the next release. + + // TODO: later version of CUBRID will provide primary_key + // property. + // When PK is defined in CUBRID, an index is automatically + // created in the db_index system table in the form of + // pk_tblname_fieldname. So the following will count how many + // columns are there which satisfy this format. + // The query will search for exact single columns, thus + // compound PK is not supported. + $res = cubrid_query($this->conn_id, + "SELECT COUNT(*) FROM db_index WHERE class_name = '" . $field->table . + "' AND is_primary_key = 'YES' AND index_name = 'pk_" . + $field->table . "_" . $field->name . "'" + ); + + if ($res) + { + $row = cubrid_fetch_array($res, CUBRID_NUM); + $F->primary_key = ($row[0] > 0 ? 1 : null); + } + else + { + $F->primary_key = null; + } + + if (is_resource($res)) + { + cubrid_close_request($res); + $this->result_id = FALSE; + } + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if(is_resource($this->result_id) || + get_resource_type($this->result_id) == "Unknown" && + preg_match('/Resource id #/', strval($this->result_id))) + { + cubrid_close_request($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return cubrid_data_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return cubrid_fetch_assoc($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return cubrid_fetch_object($this->result_id); + } + +} + + +/* End of file cubrid_result.php */ +/* Location: ./system/database/drivers/cubrid/cubrid_result.php */ \ No newline at end of file diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php new file mode 100644 index 0000000..cd16d1e --- /dev/null +++ b/system/database/drivers/cubrid/cubrid_utility.php @@ -0,0 +1,108 @@ +conn_id) + { + return "SELECT '" . $this->database . "'"; + } + else + { + return FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Optimize table query + * + * Generates a platform-specific query so that a table can be optimized + * + * @access private + * @param string the table name + * @return object + * @link http://www.cubrid.org/manual/840/en/Optimize%20Database + */ + function _optimize_table($table) + { + // No SQL based support in CUBRID as of version 8.4.0. Database or + // table optimization can be performed using CUBRID Manager + // database administration tool. See the link above for more info. + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Generates a platform-specific query so that a table can be repaired + * + * @access private + * @param string the table name + * @return object + * @link http://www.cubrid.org/manual/840/en/Checking%20Database%20Consistency + */ + function _repair_table($table) + { + // Not supported in CUBRID as of version 8.4.0. Database or + // table consistency can be checked using CUBRID Manager + // database administration tool. See the link above for more info. + return FALSE; + } + + // -------------------------------------------------------------------- + /** + * CUBRID Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + // No SQL based support in CUBRID as of version 8.4.0. Database or + // table backup can be performed using CUBRID Manager + // database administration tool. + return $this->db->display_error('db_unsuported_feature'); + } +} + +/* End of file cubrid_utility.php */ +/* Location: ./system/database/drivers/cubrid/cubrid_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/cubrid/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/index.html b/system/database/drivers/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/mssql/index.html b/system/database/drivers/mssql/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/mssql/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php new file mode 100644 index 0000000..b39bd93 --- /dev/null +++ b/system/database/drivers/mssql/mssql_driver.php @@ -0,0 +1,667 @@ +port != '') + { + $this->hostname .= ','.$this->port; + } + + return @mssql_connect($this->hostname, $this->username, $this->password); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + if ($this->port != '') + { + $this->hostname .= ','.$this->port; + } + + return @mssql_pconnect($this->hostname, $this->username, $this->password); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + // not implemented in MSSQL + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + // Note: The brackets are required in the event that the DB name + // contains reserved characters + return @mssql_select_db('['.$this->database.']', $this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return @mssql_query($sql, $this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + $this->simple_query('BEGIN TRAN'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('COMMIT TRAN'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('ROLLBACK TRAN'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + // Escape single quotes + $str = str_replace("'", "''", remove_invisible_characters($str)); + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace( + array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str + ); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @mssql_rows_affected($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * Returns the last id created in the Identity column. + * + * @access public + * @return integer + */ + function insert_id() + { + $ver = self::_parse_major_version($this->version()); + $sql = ($ver >= 8 ? "SELECT SCOPE_IDENTITY() AS last_id" : "SELECT @@IDENTITY AS last_id"); + $query = $this->query($sql); + $row = $query->row(); + return $row->last_id; + } + + // -------------------------------------------------------------------- + + /** + * Parse major version + * + * Grabs the major version number from the + * database server version string passed in. + * + * @access private + * @param string $version + * @return int16 major version number + */ + function _parse_major_version($version) + { + preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); + return $ver_info[1]; // return the major version b/c that's all we're interested in. + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return "SELECT @@VERSION AS ver"; + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; + + // for future compatibility + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return FALSE; // not currently supported + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * List column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access private + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'"; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT TOP 1 * FROM ".$table; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return mssql_get_last_message(); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + // Are error numbers supported? + return ''; + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return implode(', ', $tables); + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return "TRUNCATE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + $i = $limit + $offset; + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @mssql_close($conn_id); + } + +} + + + +/* End of file mssql_driver.php */ +/* Location: ./system/database/drivers/mssql/mssql_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php new file mode 100644 index 0000000..70b20ec --- /dev/null +++ b/system/database/drivers/mssql/mssql_forge.php @@ -0,0 +1,248 @@ +db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + // I think this syntax will work, but can find little documentation on renaming tables in MSSQL + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + +} + +/* End of file mssql_forge.php */ +/* Location: ./system/database/drivers/mssql/mssql_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php new file mode 100644 index 0000000..2897ca5 --- /dev/null +++ b/system/database/drivers/mssql/mssql_result.php @@ -0,0 +1,169 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @mssql_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + while ($field = mssql_fetch_field($this->result_id)) + { + $field_names[] = $field->name; + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + while ($field = mssql_fetch_field($this->result_id)) + { + $F = new stdClass(); + $F->name = $field->name; + $F->type = $field->type; + $F->max_length = $field->max_length; + $F->primary_key = 0; + $F->default = ''; + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_resource($this->result_id)) + { + mssql_free_result($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return mssql_data_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return mssql_fetch_assoc($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return mssql_fetch_object($this->result_id); + } + +} + + +/* End of file mssql_result.php */ +/* Location: ./system/database/drivers/mssql/mssql_result.php */ \ No newline at end of file diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php new file mode 100644 index 0000000..48ecbc7 --- /dev/null +++ b/system/database/drivers/mssql/mssql_utility.php @@ -0,0 +1,88 @@ +db->display_error('db_unsuported_feature'); + } + +} + +/* End of file mssql_utility.php */ +/* Location: ./system/database/drivers/mssql/mssql_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/mysql/index.html b/system/database/drivers/mysql/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/mysql/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php new file mode 100644 index 0000000..f87cfea --- /dev/null +++ b/system/database/drivers/mysql/mysql_driver.php @@ -0,0 +1,779 @@ +port != '') + { + $this->hostname .= ':'.$this->port; + } + + return @mysql_connect($this->hostname, $this->username, $this->password, TRUE); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + if ($this->port != '') + { + $this->hostname .= ':'.$this->port; + } + + return @mysql_pconnect($this->hostname, $this->username, $this->password); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + if (mysql_ping($this->conn_id) === FALSE) + { + $this->conn_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + return @mysql_select_db($this->database, $this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + if ( ! isset($this->use_set_names)) + { + // mysql_set_charset() requires PHP >= 5.2.3 and MySQL >= 5.0.7, use SET NAMES as fallback + $this->use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE; + } + + if ($this->use_set_names === TRUE) + { + return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id); + } + else + { + return @mysql_set_charset($charset, $this->conn_id); + } + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return "SELECT version() AS ver"; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return @mysql_query($sql, $this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + // "DELETE FROM TABLE" returns 0 affected rows This hack modifies + // the query so that it returns the number of affected rows + if ($this->delete_hack === TRUE) + { + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql)) + { + $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql); + } + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + $this->simple_query('SET AUTOCOMMIT=0'); + $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('COMMIT'); + $this->simple_query('SET AUTOCOMMIT=1'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('ROLLBACK'); + $this->simple_query('SET AUTOCOMMIT=1'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id)) + { + $str = mysql_real_escape_string($str, $this->conn_id); + } + elseif (function_exists('mysql_escape_string')) + { + $str = mysql_escape_string($str); + } + else + { + $str = addslashes($str); + } + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @mysql_affected_rows($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id() + { + return @mysql_insert_id($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'"; + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE); + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "DESCRIBE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return mysql_error($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return mysql_errno($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + + /** + * Replace statement + * + * Generates a platform-specific replace string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _replace($table, $keys, $values) + { + return "REPLACE INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert_batch($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); + } + + // -------------------------------------------------------------------- + + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key . ' = ' . $val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + // -------------------------------------------------------------------- + + + /** + * Update_Batch statement + * + * Generates a platform-specific batch update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @return string + */ + function _update_batch($table, $values, $index, $where = NULL) + { + $ids = array(); + $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : ''; + + foreach ($values as $key => $val) + { + $ids[] = $val[$index]; + + foreach (array_keys($val) as $field) + { + if ($field != $index) + { + $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; + } + } + } + + $sql = "UPDATE ".$table." SET "; + $cases = ''; + + foreach ($final as $k => $v) + { + $cases .= $k.' = CASE '."\n"; + foreach ($v as $row) + { + $cases .= $row."\n"; + } + + $cases .= 'ELSE '.$k.' END, '; + } + + $sql .= substr($cases, 0, -2); + + $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; + + return $sql; + } + + // -------------------------------------------------------------------- + + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return "TRUNCATE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + if ($offset == 0) + { + $offset = ''; + } + else + { + $offset .= ", "; + } + + return $sql."LIMIT ".$offset.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @mysql_close($conn_id); + } + +} + + +/* End of file mysql_driver.php */ +/* Location: ./system/database/drivers/mysql/mysql_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php new file mode 100644 index 0000000..c1cae13 --- /dev/null +++ b/system/database/drivers/mysql/mysql_forge.php @@ -0,0 +1,273 @@ +$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + if (array_key_exists('NAME', $attributes)) + { + $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' '; + } + + if (array_key_exists('TYPE', $attributes)) + { + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + switch ($attributes['TYPE']) + { + case 'decimal': + case 'float': + case 'numeric': + $sql .= '('.implode(',', $attributes['CONSTRAINT']).')'; + break; + + case 'enum': + case 'set': + $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")'; + break; + + default: + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + } + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param mixed the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + + $sql .= $this->_process_fields($fields); + + if (count($primary_keys) > 0) + { + $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys)); + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key_name = $this->db->_protect_identifiers(implode('_', $key)); + $key = $this->db->_protect_identifiers($key); + } + else + { + $key_name = $this->db->_protect_identifiers($key); + $key = array($key_name); + } + + $sql .= ",\n\tKEY {$key_name} (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n) DEFAULT CHARACTER SET {$this->db->char_set} COLLATE {$this->db->dbcollat};"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return string + */ + function _drop_table($table) + { + return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param array fields + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $fields, $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type "; + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql.$this->db->_protect_identifiers($fields); + } + + $sql .= $this->_process_fields($fields); + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + +} + +/* End of file mysql_forge.php */ +/* Location: ./system/database/drivers/mysql/mysql_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php new file mode 100644 index 0000000..e1a6e93 --- /dev/null +++ b/system/database/drivers/mysql/mysql_result.php @@ -0,0 +1,174 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @mysql_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + while ($field = mysql_fetch_field($this->result_id)) + { + $field_names[] = $field->name; + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + while ($field = mysql_fetch_object($this->result_id)) + { + preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches); + + $type = (array_key_exists(1, $matches)) ? $matches[1] : NULL; + $length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL; + + $F = new stdClass(); + $F->name = $field->Field; + $F->type = $type; + $F->default = $field->Default; + $F->max_length = $length; + $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 ); + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_resource($this->result_id)) + { + mysql_free_result($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return mysql_data_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return mysql_fetch_assoc($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return mysql_fetch_object($this->result_id); + } + +} + + +/* End of file mysql_result.php */ +/* Location: ./system/database/drivers/mysql/mysql_result.php */ \ No newline at end of file diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php new file mode 100644 index 0000000..48c4d63 --- /dev/null +++ b/system/database/drivers/mysql/mysql_utility.php @@ -0,0 +1,210 @@ +db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Generates a platform-specific query so that a table can be repaired + * + * @access private + * @param string the table name + * @return object + */ + function _repair_table($table) + { + return "REPAIR TABLE ".$this->db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + /** + * MySQL Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + if (count($params) == 0) + { + return FALSE; + } + + // Extract the prefs for simplicity + extract($params); + + // Build the output + $output = ''; + foreach ((array)$tables as $table) + { + // Is the table in the "ignore" list? + if (in_array($table, (array)$ignore, TRUE)) + { + continue; + } + + // Get the table schema + $query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.`'.$table.'`'); + + // No result means the table name was invalid + if ($query === FALSE) + { + continue; + } + + // Write out the table schema + $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline; + + if ($add_drop == TRUE) + { + $output .= 'DROP TABLE IF EXISTS '.$table.';'.$newline.$newline; + } + + $i = 0; + $result = $query->result_array(); + foreach ($result[0] as $val) + { + if ($i++ % 2) + { + $output .= $val.';'.$newline.$newline; + } + } + + // If inserts are not needed we're done... + if ($add_insert == FALSE) + { + continue; + } + + // Grab all the data from the current table + $query = $this->db->query("SELECT * FROM $table"); + + if ($query->num_rows() == 0) + { + continue; + } + + // Fetch the field names and determine if the field is an + // integer type. We use this info to decide whether to + // surround the data with quotes or not + + $i = 0; + $field_str = ''; + $is_int = array(); + while ($field = mysql_fetch_field($query->result_id)) + { + // Most versions of MySQL store timestamp as a string + $is_int[$i] = (in_array( + strtolower(mysql_field_type($query->result_id, $i)), + array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'), + TRUE) + ) ? TRUE : FALSE; + + // Create a string of field names + $field_str .= '`'.$field->name.'`, '; + $i++; + } + + // Trim off the end comma + $field_str = preg_replace( "/, $/" , "" , $field_str); + + + // Build the insert string + foreach ($query->result_array() as $row) + { + $val_str = ''; + + $i = 0; + foreach ($row as $v) + { + // Is the value NULL? + if ($v === NULL) + { + $val_str .= 'NULL'; + } + else + { + // Escape the data if it's not an integer + if ($is_int[$i] == FALSE) + { + $val_str .= $this->db->escape($v); + } + else + { + $val_str .= $v; + } + } + + // Append a comma + $val_str .= ', '; + $i++; + } + + // Remove the comma at the end of the string + $val_str = preg_replace( "/, $/" , "" , $val_str); + + // Build the INSERT string + $output .= 'INSERT INTO '.$table.' ('.$field_str.') VALUES ('.$val_str.');'.$newline; + } + + $output .= $newline.$newline; + } + + return $output; + } +} + +/* End of file mysql_utility.php */ +/* Location: ./system/database/drivers/mysql/mysql_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/mysqli/index.html b/system/database/drivers/mysqli/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/mysqli/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php new file mode 100644 index 0000000..d3200f3 --- /dev/null +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -0,0 +1,776 @@ +port != '') + { + return @mysqli_connect($this->hostname, $this->username, $this->password, $this->database, $this->port); + } + else + { + return @mysqli_connect($this->hostname, $this->username, $this->password, $this->database); + } + + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + return $this->db_connect(); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + if (mysqli_ping($this->conn_id) === FALSE) + { + $this->conn_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + return @mysqli_select_db($this->conn_id, $this->database); + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access private + * @param string + * @param string + * @return resource + */ + function _db_set_charset($charset, $collation) + { + if ( ! isset($this->use_set_names)) + { + // mysqli_set_charset() requires MySQL >= 5.0.7, use SET NAMES as fallback + $this->use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE; + } + + if ($this->use_set_names === TRUE) + { + return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'"); + } + else + { + return @mysqli_set_charset($this->conn_id, $charset); + } + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return "SELECT version() AS ver"; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + $result = @mysqli_query($this->conn_id, $sql); + return $result; + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + // "DELETE FROM TABLE" returns 0 affected rows This hack modifies + // the query so that it returns the number of affected rows + if ($this->delete_hack === TRUE) + { + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql)) + { + $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql); + } + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + $this->simple_query('SET AUTOCOMMIT=0'); + $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('COMMIT'); + $this->simple_query('SET AUTOCOMMIT=1'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('ROLLBACK'); + $this->simple_query('SET AUTOCOMMIT=1'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + if (function_exists('mysqli_real_escape_string') AND is_object($this->conn_id)) + { + $str = mysqli_real_escape_string($this->conn_id, $str); + } + elseif (function_exists('mysql_escape_string')) + { + $str = mysql_escape_string($str); + } + else + { + $str = addslashes($str); + } + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @mysqli_affected_rows($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id() + { + return @mysqli_insert_id($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'"; + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE); + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "DESCRIBE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return mysqli_error($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return mysqli_errno($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert_batch($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); + } + + // -------------------------------------------------------------------- + + + /** + * Replace statement + * + * Generates a platform-specific replace string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _replace($table, $keys, $values) + { + return "REPLACE INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Update_Batch statement + * + * Generates a platform-specific batch update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @return string + */ + function _update_batch($table, $values, $index, $where = NULL) + { + $ids = array(); + $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : ''; + + foreach ($values as $key => $val) + { + $ids[] = $val[$index]; + + foreach (array_keys($val) as $field) + { + if ($field != $index) + { + $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; + } + } + } + + $sql = "UPDATE ".$table." SET "; + $cases = ''; + + foreach ($final as $k => $v) + { + $cases .= $k.' = CASE '."\n"; + foreach ($v as $row) + { + $cases .= $row."\n"; + } + + $cases .= 'ELSE '.$k.' END, '; + } + + $sql .= substr($cases, 0, -2); + + $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return "TRUNCATE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + $sql .= "LIMIT ".$limit; + + if ($offset > 0) + { + $sql .= " OFFSET ".$offset; + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @mysqli_close($conn_id); + } + + +} + + +/* End of file mysqli_driver.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php new file mode 100644 index 0000000..2605494 --- /dev/null +++ b/system/database/drivers/mysqli/mysqli_forge.php @@ -0,0 +1,258 @@ +$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + if (array_key_exists('NAME', $attributes)) + { + $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' '; + } + + if (array_key_exists('TYPE', $attributes)) + { + $sql .= ' '.$attributes['TYPE']; + } + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param mixed the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + + $sql .= $this->_process_fields($fields); + + if (count($primary_keys) > 0) + { + $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys)); + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key_name = $this->db->_protect_identifiers(implode('_', $key)); + $key = $this->db->_protect_identifiers($key); + } + else + { + $key_name = $this->db->_protect_identifiers($key); + $key = array($key_name); + } + + $sql .= ",\n\tKEY {$key_name} (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n) DEFAULT CHARACTER SET {$this->db->char_set} COLLATE {$this->db->dbcollat};"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return string + */ + function _drop_table($table) + { + return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param array fields + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $fields, $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type "; + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql.$this->db->_protect_identifiers($fields); + } + + $sql .= $this->_process_fields($fields); + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + +} + +/* End of file mysqli_forge.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php new file mode 100644 index 0000000..124d4e5 --- /dev/null +++ b/system/database/drivers/mysqli/mysqli_result.php @@ -0,0 +1,174 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @mysqli_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + while ($field = mysqli_fetch_field($this->result_id)) + { + $field_names[] = $field->name; + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + while ($field = mysqli_fetch_object($this->result_id)) + { + preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches); + + $type = (array_key_exists(1, $matches)) ? $matches[1] : NULL; + $length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL; + + $F = new stdClass(); + $F->name = $field->Field; + $F->type = $type; + $F->default = $field->Default; + $F->max_length = $length; + $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 ); + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_object($this->result_id)) + { + mysqli_free_result($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return mysqli_data_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return mysqli_fetch_assoc($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return mysqli_fetch_object($this->result_id); + } + +} + + +/* End of file mysqli_result.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_result.php */ \ No newline at end of file diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php new file mode 100644 index 0000000..e17889b --- /dev/null +++ b/system/database/drivers/mysqli/mysqli_utility.php @@ -0,0 +1,87 @@ +db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Generates a platform-specific query so that a table can be repaired + * + * @access private + * @param string the table name + * @return object + */ + function _repair_table($table) + { + return "REPAIR TABLE ".$this->db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * MySQLi Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + // Currently unsupported + return $this->db->display_error('db_unsuported_feature'); + } +} + +/* End of file mysqli_utility.php */ +/* Location: ./system/database/drivers/mysqli/mysqli_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/oci8/index.html b/system/database/drivers/oci8/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/oci8/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php new file mode 100644 index 0000000..930177e --- /dev/null +++ b/system/database/drivers/oci8/oci8_driver.php @@ -0,0 +1,808 @@ +username, $this->password, $this->hostname, $this->char_set); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + public function db_pconnect() + { + return @oci_pconnect($this->username, $this->password, $this->hostname, $this->char_set); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + public function reconnect() + { + // not implemented in oracle + return; + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + public function db_select() + { + // Not in Oracle - schemas are actually usernames + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + public function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access protected + * @return string + */ + protected function _version() + { + return oci_server_version($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access protected called by the base class + * @param string an SQL query + * @return resource + */ + protected function _execute($sql) + { + // oracle must parse the query before it is run. All of the actions with + // the query are based on the statement id returned by ociparse + $this->stmt_id = FALSE; + $this->_set_stmt_id($sql); + oci_set_prefetch($this->stmt_id, 1000); + return @oci_execute($this->stmt_id, $this->_commit); + } + + /** + * Generate a statement ID + * + * @access private + * @param string an SQL query + * @return none + */ + private function _set_stmt_id($sql) + { + if ( ! is_resource($this->stmt_id)) + { + $this->stmt_id = oci_parse($this->conn_id, $this->_prep_query($sql)); + } + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + private function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * getCursor. Returns a cursor from the datbase + * + * @access public + * @return cursor id + */ + public function get_cursor() + { + $this->curs_id = oci_new_cursor($this->conn_id); + return $this->curs_id; + } + + // -------------------------------------------------------------------- + + /** + * Stored Procedure. Executes a stored procedure + * + * @access public + * @param package package stored procedure is in + * @param procedure stored procedure to execute + * @param params array of parameters + * @return array + * + * params array keys + * + * KEY OPTIONAL NOTES + * name no the name of the parameter should be in : format + * value no the value of the parameter. If this is an OUT or IN OUT parameter, + * this should be a reference to a variable + * type yes the type of the parameter + * length yes the max size of the parameter + */ + public function stored_procedure($package, $procedure, $params) + { + if ($package == '' OR $procedure == '' OR ! is_array($params)) + { + if ($this->db_debug) + { + log_message('error', 'Invalid query: '.$package.'.'.$procedure); + return $this->display_error('db_invalid_query'); + } + return FALSE; + } + + // build the query string + $sql = "begin $package.$procedure("; + + $have_cursor = FALSE; + foreach ($params as $param) + { + $sql .= $param['name'] . ","; + + if (array_key_exists('type', $param) && ($param['type'] === OCI_B_CURSOR)) + { + $have_cursor = TRUE; + } + } + $sql = trim($sql, ",") . "); end;"; + + $this->stmt_id = FALSE; + $this->_set_stmt_id($sql); + $this->_bind_params($params); + $this->query($sql, FALSE, $have_cursor); + } + + // -------------------------------------------------------------------- + + /** + * Bind parameters + * + * @access private + * @return none + */ + private function _bind_params($params) + { + if ( ! is_array($params) OR ! is_resource($this->stmt_id)) + { + return; + } + + foreach ($params as $param) + { + foreach (array('name', 'value', 'type', 'length') as $val) + { + if ( ! isset($param[$val])) + { + $param[$val] = ''; + } + } + + oci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']); + } + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + public function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + $this->_commit = OCI_DEFAULT; + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + public function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $ret = oci_commit($this->conn_id); + $this->_commit = OCI_COMMIT_ON_SUCCESS; + return $ret; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + public function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $ret = oci_rollback($this->conn_id); + $this->_commit = OCI_COMMIT_ON_SUCCESS; + return $ret; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + public function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + $str = remove_invisible_characters($str); + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace( array('%', '_', $this->_like_escape_chr), + array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + public function affected_rows() + { + return @oci_num_rows($this->stmt_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + public function insert_id() + { + // not supported in oracle + return $this->display_error('db_unsupported_function'); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + public function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query == FALSE) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * Show table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access protected + * @param boolean + * @return string + */ + protected function _list_tables($prefix_limit = FALSE) + { + $sql = "SELECT TABLE_NAME FROM ALL_TABLES"; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + $sql .= " WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access protected + * @param string the table name + * @return string + */ + protected function _list_columns($table = '') + { + return "SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = '$table'"; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + protected function _field_data($table) + { + return "SELECT * FROM ".$table." where rownum = 1"; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access protected + * @return string + */ + protected function _error_message() + { + // If the error was during connection, no conn_id should be passed + $error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error(); + return $error['message']; + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access protected + * @return integer + */ + protected function _error_number() + { + // Same as _error_message() + $error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error(); + return $error['code']; + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access protected + * @param string + * @return string + */ + protected function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access protected + * @param type + * @return type + */ + protected function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return implode(', ', $tables); + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + protected function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access protected + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + protected function _insert_batch($table, $keys, $values) + { + $keys = implode(', ', $keys); + $sql = "INSERT ALL\n"; + + for ($i = 0, $c = count($values); $i < $c; $i++) + { + $sql .= ' INTO ' . $table . ' (' . $keys . ') VALUES ' . $values[$i] . "\n"; + } + + $sql .= 'SELECT * FROM dual'; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access protected + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access protected + * @param string the table name + * @return string + */ + protected function _truncate($table) + { + return "TRUNCATE TABLE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access protected + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + protected function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access protected + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + protected function _limit($sql, $limit, $offset) + { + $limit = $offset + $limit; + $newsql = "SELECT * FROM (select inner_query.*, rownum rnum FROM ($sql) inner_query WHERE rownum < $limit)"; + + if ($offset != 0) + { + $newsql .= " WHERE rnum >= $offset"; + } + + // remember that we used limits + $this->limit_used = TRUE; + + return $newsql; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access protected + * @param resource + * @return void + */ + protected function _close($conn_id) + { + @oci_close($conn_id); + } + + +} + + + +/* End of file oci8_driver.php */ +/* Location: ./system/database/drivers/oci8/oci8_driver.php */ diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php new file mode 100644 index 0000000..3cd1758 --- /dev/null +++ b/system/database/drivers/oci8/oci8_forge.php @@ -0,0 +1,248 @@ +db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tUNIQUE COLUMNS (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return bool + */ + function _drop_table($table) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + + +} + +/* End of file oci8_forge.php */ +/* Location: ./system/database/drivers/oci8/oci8_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php new file mode 100644 index 0000000..3421278 --- /dev/null +++ b/system/database/drivers/oci8/oci8_result.php @@ -0,0 +1,217 @@ +num_rows === 0 && count($this->result_array()) > 0) + { + $this->num_rows = count($this->result_array()); + @oci_execute($this->stmt_id); + + if ($this->curs_id) + { + @oci_execute($this->curs_id); + } + } + + return $this->num_rows; + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + public function num_fields() + { + $count = @oci_num_fields($this->stmt_id); + + // if we used a limit we subtract it + if ($this->limit_used) + { + $count = $count - 1; + } + + return $count; + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + public function list_fields() + { + $field_names = array(); + for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++) + { + $field_names[] = oci_field_name($this->stmt_id, $c); + } + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + public function field_data() + { + $retval = array(); + for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++) + { + $F = new stdClass(); + $F->name = oci_field_name($this->stmt_id, $c); + $F->type = oci_field_type($this->stmt_id, $c); + $F->max_length = oci_field_size($this->stmt_id, $c); + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + public function free_result() + { + if (is_resource($this->result_id)) + { + oci_free_statement($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access protected + * @return array + */ + protected function _fetch_assoc() + { + $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id; + return oci_fetch_assoc($id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access protected + * @return object + */ + protected function _fetch_object() + { + $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id; + return @oci_fetch_object($id); + } + + // -------------------------------------------------------------------- + + /** + * Query result. "array" version. + * + * @access public + * @return array + */ + public function result_array() + { + if (count($this->result_array) > 0) + { + return $this->result_array; + } + + $row = NULL; + while ($row = $this->_fetch_assoc()) + { + $this->result_array[] = $row; + } + + return $this->result_array; + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access protected + * @return array + */ + protected function _data_seek($n = 0) + { + return FALSE; // Not needed + } + +} + + +/* End of file oci8_result.php */ +/* Location: ./system/database/drivers/oci8/oci8_result.php */ diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php new file mode 100644 index 0000000..854b467 --- /dev/null +++ b/system/database/drivers/oci8/oci8_utility.php @@ -0,0 +1,87 @@ +db->display_error('db_unsuported_feature'); + } +} + +/* End of file oci8_utility.php */ +/* Location: ./system/database/drivers/oci8/oci8_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/odbc/index.html b/system/database/drivers/odbc/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/odbc/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php new file mode 100644 index 0000000..bcd7937 --- /dev/null +++ b/system/database/drivers/odbc/odbc_driver.php @@ -0,0 +1,637 @@ +_random_keyword = ' RND('.time().')'; // database specific random keyword + } + + /** + * Non-persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_connect() + { + return @odbc_connect($this->hostname, $this->username, $this->password); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + return @odbc_pconnect($this->hostname, $this->username, $this->password); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + // not implemented in odbc + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + // Not needed for ODBC + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return "SELECT version() AS ver"; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return @odbc_exec($this->conn_id, $sql); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + return odbc_autocommit($this->conn_id, FALSE); + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $ret = odbc_commit($this->conn_id); + odbc_autocommit($this->conn_id, TRUE); + return $ret; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $ret = odbc_rollback($this->conn_id); + odbc_autocommit($this->conn_id, TRUE); + return $ret; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + // ODBC doesn't require escaping + $str = remove_invisible_characters($str); + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace( array('%', '_', $this->_like_escape_chr), + array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @odbc_num_rows($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id() + { + return @odbc_insert_id($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * Show table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SHOW TABLES FROM `".$this->database."`"; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return FALSE; // not currently supported + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SHOW COLUMNS FROM ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT TOP 1 FROM ".$table; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return odbc_errormsg($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return odbc_error($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return $this->_delete($table); + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + // Does ODBC doesn't use the LIMIT clause? + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @odbc_close($conn_id); + } + + +} + + + +/* End of file odbc_driver.php */ +/* Location: ./system/database/drivers/odbc/odbc_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php new file mode 100644 index 0000000..3ec86b4 --- /dev/null +++ b/system/database/drivers/odbc/odbc_forge.php @@ -0,0 +1,266 @@ +db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Drop database + * + * @access private + * @param string the database name + * @return bool + */ + function _drop_database($name) + { + // ODBC has no "drop database" command since it's + // designed to connect to an existing database + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return bool + */ + function _drop_table($table) + { + // Not a supported ODBC feature + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + + +} + +/* End of file odbc_forge.php */ +/* Location: ./system/database/drivers/odbc/odbc_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php new file mode 100644 index 0000000..5d64a46 --- /dev/null +++ b/system/database/drivers/odbc/odbc_result.php @@ -0,0 +1,228 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @odbc_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + for ($i = 0; $i < $this->num_fields(); $i++) + { + $field_names[] = odbc_field_name($this->result_id, $i); + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + for ($i = 0; $i < $this->num_fields(); $i++) + { + $F = new stdClass(); + $F->name = odbc_field_name($this->result_id, $i); + $F->type = odbc_field_type($this->result_id, $i); + $F->max_length = odbc_field_len($this->result_id, $i); + $F->primary_key = 0; + $F->default = ''; + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_resource($this->result_id)) + { + odbc_free_result($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + if (function_exists('odbc_fetch_object')) + { + return odbc_fetch_array($this->result_id); + } + else + { + return $this->_odbc_fetch_array($this->result_id); + } + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + if (function_exists('odbc_fetch_object')) + { + return odbc_fetch_object($this->result_id); + } + else + { + return $this->_odbc_fetch_object($this->result_id); + } + } + + + /** + * Result - object + * + * subsititutes the odbc_fetch_object function when + * not available (odbc_fetch_object requires unixODBC) + * + * @access private + * @return object + */ + function _odbc_fetch_object(& $odbc_result) { + $rs = array(); + $rs_obj = FALSE; + if (odbc_fetch_into($odbc_result, $rs)) { + foreach ($rs as $k=>$v) { + $field_name= odbc_field_name($odbc_result, $k+1); + $rs_obj->$field_name = $v; + } + } + return $rs_obj; + } + + + /** + * Result - array + * + * subsititutes the odbc_fetch_array function when + * not available (odbc_fetch_array requires unixODBC) + * + * @access private + * @return array + */ + function _odbc_fetch_array(& $odbc_result) { + $rs = array(); + $rs_assoc = FALSE; + if (odbc_fetch_into($odbc_result, $rs)) { + $rs_assoc=array(); + foreach ($rs as $k=>$v) { + $field_name= odbc_field_name($odbc_result, $k+1); + $rs_assoc[$field_name] = $v; + } + } + return $rs_assoc; + } + +} + + +/* End of file odbc_result.php */ +/* Location: ./system/database/drivers/odbc/odbc_result.php */ \ No newline at end of file diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php new file mode 100644 index 0000000..d335bed --- /dev/null +++ b/system/database/drivers/odbc/odbc_utility.php @@ -0,0 +1,103 @@ +db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Optimize table query + * + * Generates a platform-specific query so that a table can be optimized + * + * @access private + * @param string the table name + * @return object + */ + function _optimize_table($table) + { + // Not a supported ODBC feature + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Generates a platform-specific query so that a table can be repaired + * + * @access private + * @param string the table name + * @return object + */ + function _repair_table($table) + { + // Not a supported ODBC feature + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * ODBC Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + // Currently unsupported + return $this->db->display_error('db_unsuported_feature'); + } + +} + +/* End of file odbc_utility.php */ +/* Location: ./system/database/drivers/odbc/odbc_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/pdo/index.html b/system/database/drivers/pdo/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/pdo/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php new file mode 100644 index 0000000..1ecc90a --- /dev/null +++ b/system/database/drivers/pdo/pdo_driver.php @@ -0,0 +1,812 @@ +hostname, 'mysql') !== FALSE) + { + $this->_like_escape_str = ''; + $this->_like_escape_chr = ''; + + //Prior to this version, the charset can't be set in the dsn + if(is_php('5.3.6')) + { + $this->hostname .= ";charset={$this->char_set}"; + } + + //Set the charset with the connection options + $this->options['PDO::MYSQL_ATTR_INIT_COMMAND'] = "SET NAMES {$this->char_set}"; + } + elseif (strpos($this->hostname, 'odbc') !== FALSE) + { + $this->_like_escape_str = " {escape '%s'} "; + $this->_like_escape_chr = '!'; + } + else + { + $this->_like_escape_str = " ESCAPE '%s' "; + $this->_like_escape_chr = '!'; + } + + empty($this->database) OR $this->hostname .= ';dbname='.$this->database; + + $this->trans_enabled = FALSE; + + $this->_random_keyword = ' RND('.time().')'; // database specific random keyword + } + + /** + * Non-persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_connect() + { + $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT; + + return new PDO($this->hostname, $this->username, $this->password, $this->options); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT; + $this->options['PDO::ATTR_PERSISTENT'] = TRUE; + + return new PDO($this->hostname, $this->username, $this->password, $this->options); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + // Not needed for PDO + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return $this->conn_id->getAttribute(PDO::ATTR_CLIENT_VERSION); + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return object + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + $result_id = $this->conn_id->prepare($sql); + $result_id->execute(); + + if (is_object($result_id)) + { + if (is_numeric(stripos($sql, 'SELECT'))) + { + $this->affect_rows = count($result_id->fetchAll()); + $result_id->execute(); + } + else + { + $this->affect_rows = $result_id->rowCount(); + } + } + else + { + $this->affect_rows = 0; + } + + return $result_id; + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = (bool) ($test_mode === TRUE); + + return $this->conn_id->beginTransaction(); + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $ret = $this->conn->commit(); + return $ret; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $ret = $this->conn_id->rollBack(); + return $ret; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + //Escape the string + $str = $this->conn_id->quote($str); + + //If there are duplicated quotes, trim them away + if (strpos($str, "'") === 0) + { + $str = substr($str, 1, -1); + } + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace( array('%', '_', $this->_like_escape_chr), + array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return $this->affect_rows; + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id($name=NULL) + { + //Convenience method for postgres insertid + if (strpos($this->hostname, 'pgsql') !== FALSE) + { + $v = $this->_version(); + + $table = func_num_args() > 0 ? func_get_arg(0) : NULL; + + if ($table == NULL && $v >= '8.1') + { + $sql='SELECT LASTVAL() as ins_id'; + } + $query = $this->query($sql); + $row = $query->row(); + return $row->ins_id; + } + else + { + return $this->conn_id->lastInsertId($name); + } + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * Show table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SHOW TABLES FROM `".$this->database."`"; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return FALSE; // not currently supported + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SHOW COLUMNS FROM ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT TOP 1 FROM ".$table; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + $error_array = $this->conn_id->errorInfo(); + return $error_array[2]; + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return $this->conn_id->errorCode(); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return (count($tables) == 1) ? $tables[0] : '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert_batch($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Update_Batch statement + * + * Generates a platform-specific batch update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @return string + */ + function _update_batch($table, $values, $index, $where = NULL) + { + $ids = array(); + $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : ''; + + foreach ($values as $key => $val) + { + $ids[] = $val[$index]; + + foreach (array_keys($val) as $field) + { + if ($field != $index) + { + $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field]; + } + } + } + + $sql = "UPDATE ".$table." SET "; + $cases = ''; + + foreach ($final as $k => $v) + { + $cases .= $k.' = CASE '."\n"; + foreach ($v as $row) + { + $cases .= $row."\n"; + } + + $cases .= 'ELSE '.$k.' END, '; + } + + $sql .= substr($cases, 0, -2); + + $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')'; + + return $sql; + } + + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return $this->_delete($table); + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + if (strpos($this->hostname, 'cubrid') !== FALSE || strpos($this->hostname, 'sqlite') !== FALSE) + { + if ($offset == 0) + { + $offset = ''; + } + else + { + $offset .= ", "; + } + + return $sql."LIMIT ".$offset.$limit; + } + else + { + $sql .= "LIMIT ".$limit; + + if ($offset > 0) + { + $sql .= " OFFSET ".$offset; + } + + return $sql; + } + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + $this->conn_id = null; + } + + +} + + + +/* End of file pdo_driver.php */ +/* Location: ./system/database/drivers/pdo/pdo_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php new file mode 100644 index 0000000..9a78220 --- /dev/null +++ b/system/database/drivers/pdo/pdo_forge.php @@ -0,0 +1,266 @@ +db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Drop database + * + * @access private + * @param string the database name + * @return bool + */ + function _drop_database($name) + { + // PDO has no "drop database" command since it's + // designed to connect to an existing database + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return bool + */ + function _drop_table($table) + { + // Not a supported PDO feature + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + + +} + +/* End of file pdo_forge.php */ +/* Location: ./system/database/drivers/pdo/pdo_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php new file mode 100644 index 0000000..44fdd6d --- /dev/null +++ b/system/database/drivers/pdo/pdo_result.php @@ -0,0 +1,183 @@ +num_rows)) + { + return $this->num_rows; + } + elseif (($this->num_rows = $this->result_id->rowCount()) > 0) + { + return $this->num_rows; + } + + $this->num_rows = count($this->result_id->fetchAll()); + $this->result_id->execute(); + return $this->num_rows; + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return $this->result_id->columnCount(); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $data = array(); + + try + { + for($i = 0; $i < $this->num_fields(); $i++) + { + $data[] = $this->result_id->getColumnMeta($i); + } + + return $data; + } + catch (Exception $e) + { + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_object($this->result_id)) + { + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return $this->result_id->fetch(PDO::FETCH_ASSOC); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return $this->result_id->fetchObject(); + } + +} + + +/* End of file pdo_result.php */ +/* Location: ./system/database/drivers/pdo/pdo_result.php */ \ No newline at end of file diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php new file mode 100644 index 0000000..88ce033 --- /dev/null +++ b/system/database/drivers/pdo/pdo_utility.php @@ -0,0 +1,103 @@ +db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Optimize table query + * + * Generates a platform-specific query so that a table can be optimized + * + * @access private + * @param string the table name + * @return object + */ + function _optimize_table($table) + { + // Not a supported PDO feature + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Generates a platform-specific query so that a table can be repaired + * + * @access private + * @param string the table name + * @return object + */ + function _repair_table($table) + { + // Not a supported PDO feature + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * PDO Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + // Currently unsupported + return $this->db->display_error('db_unsuported_feature'); + } + +} + +/* End of file pdo_utility.php */ +/* Location: ./system/database/drivers/pdo/pdo_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/postgre/index.html b/system/database/drivers/postgre/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/postgre/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php new file mode 100644 index 0000000..5367f97 --- /dev/null +++ b/system/database/drivers/postgre/postgre_driver.php @@ -0,0 +1,703 @@ + 'host', + 'port' => 'port', + 'database' => 'dbname', + 'username' => 'user', + 'password' => 'password' + ); + + $connect_string = ""; + foreach ($components as $key => $val) + { + if (isset($this->$key) && $this->$key != '') + { + $connect_string .= " $val=".$this->$key; + } + } + return trim($connect_string); + } + + // -------------------------------------------------------------------- + + /** + * Non-persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_connect() + { + return @pg_connect($this->_connect_string()); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + return @pg_pconnect($this->_connect_string()); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + if (pg_ping($this->conn_id) === FALSE) + { + $this->conn_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + // Not needed for Postgre so we'll return TRUE + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return "SELECT version() AS ver"; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return @pg_query($this->conn_id, $sql); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + return @pg_exec($this->conn_id, "begin"); + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + return @pg_exec($this->conn_id, "commit"); + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + return @pg_exec($this->conn_id, "rollback"); + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + $str = pg_escape_string($str); + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace( array('%', '_', $this->_like_escape_chr), + array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @pg_affected_rows($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id() + { + $v = $this->_version(); + $v = $v['server']; + + $table = func_num_args() > 0 ? func_get_arg(0) : NULL; + $column = func_num_args() > 1 ? func_get_arg(1) : NULL; + + if ($table == NULL && $v >= '8.1') + { + $sql='SELECT LASTVAL() as ins_id'; + } + elseif ($table != NULL && $column != NULL && $v >= '8.0') + { + $sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column); + $query = $this->query($sql); + $row = $query->row(); + $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq); + } + elseif ($table != NULL) + { + // seq_name passed in table parameter + $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table); + } + else + { + return pg_last_oid($this->result_id); + } + $query = $this->query($sql); + $row = $query->row(); + return $row->ins_id; + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * Show table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + $sql .= " AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SELECT column_name FROM information_schema.columns WHERE table_name ='".$table."'"; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT * FROM ".$table." LIMIT 1"; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return pg_last_error($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return ''; + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return implode(', ', $tables); + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert_batch($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return "TRUNCATE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + $sql .= "LIMIT ".$limit; + + if ($offset > 0) + { + $sql .= " OFFSET ".$offset; + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @pg_close($conn_id); + } + + +} + + +/* End of file postgre_driver.php */ +/* Location: ./system/database/drivers/postgre/postgre_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php new file mode 100644 index 0000000..91a1c68 --- /dev/null +++ b/system/database/drivers/postgre/postgre_forge.php @@ -0,0 +1,299 @@ +db->table_exists($table)) + { + return "SELECT * FROM $table"; // Needs to return innocous but valid SQL statement + } + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $is_unsigned = (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE); + + // Convert datatypes to be PostgreSQL-compatible + switch (strtoupper($attributes['TYPE'])) + { + case 'TINYINT': + $attributes['TYPE'] = 'SMALLINT'; + break; + case 'SMALLINT': + $attributes['TYPE'] = ($is_unsigned) ? 'INTEGER' : 'SMALLINT'; + break; + case 'MEDIUMINT': + $attributes['TYPE'] = 'INTEGER'; + break; + case 'INT': + $attributes['TYPE'] = ($is_unsigned) ? 'BIGINT' : 'INTEGER'; + break; + case 'BIGINT': + $attributes['TYPE'] = ($is_unsigned) ? 'NUMERIC' : 'BIGINT'; + break; + case 'DOUBLE': + $attributes['TYPE'] = 'DOUBLE PRECISION'; + break; + case 'DATETIME': + $attributes['TYPE'] = 'TIMESTAMP'; + break; + case 'LONGTEXT': + $attributes['TYPE'] = 'TEXT'; + break; + case 'BLOB': + $attributes['TYPE'] = 'BYTEA'; + break; + } + + // If this is an auto-incrementing primary key, use the serial data type instead + if (in_array($field, $primary_keys) && array_key_exists('AUTO_INCREMENT', $attributes) + && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' SERIAL'; + } + else + { + $sql .= ' '.$attributes['TYPE']; + } + + // Modified to prevent constraints with integer data types + if (array_key_exists('CONSTRAINT', $attributes) && strpos($attributes['TYPE'], 'INT') === false) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + // Added new attribute to create unqite fields. Also works with MySQL + if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE) + { + $sql .= ' UNIQUE'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + // Something seems to break when passing an array to _protect_identifiers() + foreach ($primary_keys as $index => $key) + { + $primary_keys[$index] = $this->db->_protect_identifiers($key); + } + + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + $sql .= "\n);"; + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + foreach ($key as $field) + { + $sql .= "CREATE INDEX " . $table . "_" . str_replace(array('"', "'"), '', $field) . "_index ON $table ($field); "; + } + } + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * @access private + * @return bool + */ + function _drop_table($table) + { + return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table)." CASCADE"; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + + +} + +/* End of file postgre_forge.php */ +/* Location: ./system/database/drivers/postgre/postgre_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php new file mode 100644 index 0000000..e9a1d16 --- /dev/null +++ b/system/database/drivers/postgre/postgre_result.php @@ -0,0 +1,169 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @pg_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + for ($i = 0; $i < $this->num_fields(); $i++) + { + $field_names[] = pg_field_name($this->result_id, $i); + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + for ($i = 0; $i < $this->num_fields(); $i++) + { + $F = new stdClass(); + $F->name = pg_field_name($this->result_id, $i); + $F->type = pg_field_type($this->result_id, $i); + $F->max_length = pg_field_size($this->result_id, $i); + $F->primary_key = 0; + $F->default = ''; + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_resource($this->result_id)) + { + pg_free_result($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return pg_result_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return pg_fetch_assoc($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return pg_fetch_object($this->result_id); + } + +} + + +/* End of file postgre_result.php */ +/* Location: ./system/database/drivers/postgre/postgre_result.php */ \ No newline at end of file diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php new file mode 100644 index 0000000..741c52e --- /dev/null +++ b/system/database/drivers/postgre/postgre_utility.php @@ -0,0 +1,88 @@ +db->display_error('db_unsuported_feature'); + } +} + + +/* End of file postgre_utility.php */ +/* Location: ./system/database/drivers/postgre/postgre_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlite/index.html b/system/database/drivers/sqlite/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/sqlite/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php new file mode 100644 index 0000000..0cc898b --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_driver.php @@ -0,0 +1,658 @@ +database, FILE_WRITE_MODE, $error)) + { + log_message('error', $error); + + if ($this->db_debug) + { + $this->display_error($error, '', TRUE); + } + + return FALSE; + } + + return $conn_id; + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + if ( ! $conn_id = @sqlite_popen($this->database, FILE_WRITE_MODE, $error)) + { + log_message('error', $error); + + if ($this->db_debug) + { + $this->display_error($error, '', TRUE); + } + + return FALSE; + } + + return $conn_id; + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + // not implemented in SQLite + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + return sqlite_libversion(); + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return @sqlite_query($this->conn_id, $sql); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + $this->simple_query('BEGIN TRANSACTION'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('COMMIT'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + $this->simple_query('ROLLBACK'); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = $this->escape_str($val, $like); + } + + return $str; + } + + $str = sqlite_escape_string($str); + + // escape LIKE condition wildcards + if ($like === TRUE) + { + $str = str_replace( array('%', '_', $this->_like_escape_chr), + array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), + $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return sqlite_changes($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @access public + * @return integer + */ + function insert_id() + { + return @sqlite_last_insert_rowid($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + { + return 0; + } + + $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE)); + + if ($query->num_rows() == 0) + { + return 0; + } + + $row = $query->row(); + $this->_reset_select(); + return (int) $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + $sql = "SELECT name from sqlite_master WHERE type='table'"; + + if ($prefix_limit !== FALSE AND $this->dbprefix != '') + { + $sql .= " AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + } + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access public + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + // Not supported + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT * FROM ".$table." LIMIT 1"; + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + return sqlite_error_string(sqlite_last_error($this->conn_id)); + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + return sqlite_last_error($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + if ($this->_escape_char == '') + { + return $item; + } + + foreach ($this->_reserved_identifiers as $id) + { + if (strpos($item, '.'.$id) !== FALSE) + { + $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item); + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + } + + if (strpos($item, '.') !== FALSE) + { + $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char; + } + else + { + $str = $this->_escape_char.$item.$this->_escape_char; + } + + // remove duplicates if the user already included the escape + return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str); + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return '('.implode(', ', $tables).')'; + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where, $orderby = array(), $limit = FALSE) + { + foreach ($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):''; + + $sql = "UPDATE ".$table." SET ".implode(', ', $valstr); + + $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : ''; + + $sql .= $orderby.$limit; + + return $sql; + } + + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return $this->_delete($table); + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where = array(), $like = array(), $limit = FALSE) + { + $conditions = ''; + + if (count($where) > 0 OR count($like) > 0) + { + $conditions = "\nWHERE "; + $conditions .= implode("\n", $this->ar_where); + + if (count($where) > 0 && count($like) > 0) + { + $conditions .= " AND "; + } + $conditions .= implode("\n", $like); + } + + $limit = ( ! $limit) ? '' : ' LIMIT '.$limit; + + return "DELETE FROM ".$table.$conditions.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + if ($offset == 0) + { + $offset = ''; + } + else + { + $offset .= ", "; + } + + return $sql."LIMIT ".$offset.$limit; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @sqlite_close($conn_id); + } + + +} + + +/* End of file sqlite_driver.php */ +/* Location: ./system/database/drivers/sqlite/sqlite_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php new file mode 100644 index 0000000..5690408 --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_forge.php @@ -0,0 +1,265 @@ +db->database) OR ! @unlink($this->db->database)) + { + if ($this->db->db_debug) + { + return $this->db->display_error('db_unable_to_drop'); + } + return FALSE; + } + return TRUE; + } + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + // IF NOT EXISTS added to SQLite in 3.3.0 + if ($if_not_exists === TRUE && version_compare($this->db->_version(), '3.3.0', '>=') === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)."("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tUNIQUE (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Drop Table + * + * Unsupported feature in SQLite + * + * @access private + * @return bool + */ + function _drop_table($table) + { + if ($this->db->db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return array(); + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + // SQLite does not support dropping columns + // http://www.sqlite.org/omitted.html + // http://www.sqlite.org/faq.html#q11 + return FALSE; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } +} + +/* End of file sqlite_forge.php */ +/* Location: ./system/database/drivers/sqlite/sqlite_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php new file mode 100644 index 0000000..7bd30db --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_result.php @@ -0,0 +1,179 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @sqlite_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + for ($i = 0; $i < $this->num_fields(); $i++) + { + $field_names[] = sqlite_field_name($this->result_id, $i); + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + for ($i = 0; $i < $this->num_fields(); $i++) + { + $F = new stdClass(); + $F->name = sqlite_field_name($this->result_id, $i); + $F->type = 'varchar'; + $F->max_length = 0; + $F->primary_key = 0; + $F->default = ''; + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + // Not implemented in SQLite + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + return sqlite_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return sqlite_fetch_array($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + if (function_exists('sqlite_fetch_object')) + { + return sqlite_fetch_object($this->result_id); + } + else + { + $arr = sqlite_fetch_array($this->result_id, SQLITE_ASSOC); + if (is_array($arr)) + { + $obj = (object) $arr; + return $obj; + } else { + return NULL; + } + } + } + +} + + +/* End of file sqlite_result.php */ +/* Location: ./system/database/drivers/sqlite/sqlite_result.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php new file mode 100644 index 0000000..508023e --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_utility.php @@ -0,0 +1,96 @@ +db_debug) + { + return $this->db->display_error('db_unsuported_feature'); + } + return array(); + } + + // -------------------------------------------------------------------- + + /** + * Optimize table query + * + * Is optimization even supported in SQLite? + * + * @access private + * @param string the table name + * @return object + */ + function _optimize_table($table) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Repair table query + * + * Are table repairs even supported in SQLite? + * + * @access private + * @param string the table name + * @return object + */ + function _repair_table($table) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * SQLite Export + * + * @access private + * @param array Preferences + * @return mixed + */ + function _backup($params = array()) + { + // Currently unsupported + return $this->db->display_error('db_unsuported_feature'); + } +} + +/* End of file sqlite_utility.php */ +/* Location: ./system/database/drivers/sqlite/sqlite_utility.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/drivers/sqlsrv/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php new file mode 100644 index 0000000..400fd31 --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -0,0 +1,599 @@ +char_set)) ? 'UTF-8' : $this->char_set; + + $connection = array( + 'UID' => empty($this->username) ? '' : $this->username, + 'PWD' => empty($this->password) ? '' : $this->password, + 'Database' => $this->database, + 'ConnectionPooling' => $pooling ? 1 : 0, + 'CharacterSet' => $character_set, + 'ReturnDatesAsStrings' => 1 + ); + + // If the username and password are both empty, assume this is a + // 'Windows Authentication Mode' connection. + if(empty($connection['UID']) && empty($connection['PWD'])) { + unset($connection['UID'], $connection['PWD']); + } + + return sqlsrv_connect($this->hostname, $connection); + } + + // -------------------------------------------------------------------- + + /** + * Persistent database connection + * + * @access private called by the base class + * @return resource + */ + function db_pconnect() + { + $this->db_connect(TRUE); + } + + // -------------------------------------------------------------------- + + /** + * Reconnect + * + * Keep / reestablish the db connection if no queries have been + * sent for a length of time exceeding the server's idle timeout + * + * @access public + * @return void + */ + function reconnect() + { + // not implemented in MSSQL + } + + // -------------------------------------------------------------------- + + /** + * Select the database + * + * @access private called by the base class + * @return resource + */ + function db_select() + { + return $this->_execute('USE ' . $this->database); + } + + // -------------------------------------------------------------------- + + /** + * Set client character set + * + * @access public + * @param string + * @param string + * @return resource + */ + function db_set_charset($charset, $collation) + { + // @todo - add support if needed + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @access private called by the base class + * @param string an SQL query + * @return resource + */ + function _execute($sql) + { + $sql = $this->_prep_query($sql); + return sqlsrv_query($this->conn_id, $sql, null, array( + 'Scrollable' => SQLSRV_CURSOR_STATIC, + 'SendStreamParamsAtExec' => true + )); + } + + // -------------------------------------------------------------------- + + /** + * Prep the query + * + * If needed, each database adapter can prep the query string + * + * @access private called by execute() + * @param string an SQL query + * @return string + */ + function _prep_query($sql) + { + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @access public + * @return bool + */ + function trans_begin($test_mode = FALSE) + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + // Reset the transaction failure flag. + // If the $test_mode flag is set to TRUE transactions will be rolled back + // even if the queries produce a successful result. + $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE; + + return sqlsrv_begin_transaction($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @access public + * @return bool + */ + function trans_commit() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + return sqlsrv_commit($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @access public + * @return bool + */ + function trans_rollback() + { + if ( ! $this->trans_enabled) + { + return TRUE; + } + + // When transactions are nested we only begin/commit/rollback the outermost ones + if ($this->_trans_depth > 0) + { + return TRUE; + } + + return sqlsrv_rollback($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Escape String + * + * @access public + * @param string + * @param bool whether or not the string will be used in a LIKE condition + * @return string + */ + function escape_str($str, $like = FALSE) + { + // Escape single quotes + return str_replace("'", "''", $str); + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @access public + * @return integer + */ + function affected_rows() + { + return @sqlrv_rows_affected($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * Returns the last id created in the Identity column. + * + * @access public + * @return integer + */ + function insert_id() + { + return $this->query('select @@IDENTITY as insert_id')->row('insert_id'); + } + + // -------------------------------------------------------------------- + + /** + * Parse major version + * + * Grabs the major version number from the + * database server version string passed in. + * + * @access private + * @param string $version + * @return int16 major version number + */ + function _parse_major_version($version) + { + preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); + return $ver_info[1]; // return the major version b/c that's all we're interested in. + } + + // -------------------------------------------------------------------- + + /** + * Version number query string + * + * @access public + * @return string + */ + function _version() + { + $info = sqlsrv_server_info($this->conn_id); + return sprintf("select '%s' as ver", $info['SQLServerVersion']); + } + + // -------------------------------------------------------------------- + + /** + * "Count All" query + * + * Generates a platform-specific query string that counts all records in + * the specified database + * + * @access public + * @param string + * @return string + */ + function count_all($table = '') + { + if ($table == '') + return '0'; + + $query = $this->query("SELECT COUNT(*) AS numrows FROM " . $this->dbprefix . $table); + + if ($query->num_rows() == 0) + return '0'; + + $row = $query->row(); + $this->_reset_select(); + return $row->numrows; + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @access private + * @param boolean + * @return string + */ + function _list_tables($prefix_limit = FALSE) + { + return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; + } + + // -------------------------------------------------------------------- + + /** + * List column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @access private + * @param string the table name + * @return string + */ + function _list_columns($table = '') + { + return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->_escape_table($table)."'"; + } + + // -------------------------------------------------------------------- + + /** + * Field data query + * + * Generates a platform-specific query so that the column data can be retrieved + * + * @access public + * @param string the table name + * @return object + */ + function _field_data($table) + { + return "SELECT TOP 1 * FROM " . $this->_escape_table($table); + } + + // -------------------------------------------------------------------- + + /** + * The error message string + * + * @access private + * @return string + */ + function _error_message() + { + $error = array_shift(sqlsrv_errors()); + return !empty($error['message']) ? $error['message'] : null; + } + + // -------------------------------------------------------------------- + + /** + * The error message number + * + * @access private + * @return integer + */ + function _error_number() + { + $error = array_shift(sqlsrv_errors()); + return isset($error['SQLSTATE']) ? $error['SQLSTATE'] : null; + } + + // -------------------------------------------------------------------- + + /** + * Escape Table Name + * + * This function adds backticks if the table name has a period + * in it. Some DBs will get cranky unless periods are escaped + * + * @access private + * @param string the table name + * @return string + */ + function _escape_table($table) + { + return $table; + } + + + /** + * Escape the SQL Identifiers + * + * This function escapes column and table names + * + * @access private + * @param string + * @return string + */ + function _escape_identifiers($item) + { + return $item; + } + + // -------------------------------------------------------------------- + + /** + * From Tables + * + * This function implicitly groups FROM tables so there is no confusion + * about operator precedence in harmony with SQL standards + * + * @access public + * @param type + * @return type + */ + function _from_tables($tables) + { + if ( ! is_array($tables)) + { + $tables = array($tables); + } + + return implode(', ', $tables); + } + + // -------------------------------------------------------------------- + + /** + * Insert statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert($table, $keys, $values) + { + return "INSERT INTO ".$this->_escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")"; + } + + // -------------------------------------------------------------------- + + /** + * Update statement + * + * Generates a platform-specific update string from the supplied data + * + * @access public + * @param string the table name + * @param array the update data + * @param array the where clause + * @param array the orderby clause + * @param array the limit clause + * @return string + */ + function _update($table, $values, $where) + { + foreach($values as $key => $val) + { + $valstr[] = $key." = ".$val; + } + + return "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where); + } + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * If the database does not support the truncate() command + * This function maps to "DELETE FROM table" + * + * @access public + * @param string the table name + * @return string + */ + function _truncate($table) + { + return "TRUNCATE ".$table; + } + + // -------------------------------------------------------------------- + + /** + * Delete statement + * + * Generates a platform-specific delete string from the supplied data + * + * @access public + * @param string the table name + * @param array the where clause + * @param string the limit clause + * @return string + */ + function _delete($table, $where) + { + return "DELETE FROM ".$this->_escape_table($table)." WHERE ".implode(" ", $where); + } + + // -------------------------------------------------------------------- + + /** + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @access public + * @param string the sql query string + * @param integer the number of rows to limit the query to + * @param integer the offset value + * @return string + */ + function _limit($sql, $limit, $offset) + { + $i = $limit + $offset; + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql); + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @access public + * @param resource + * @return void + */ + function _close($conn_id) + { + @sqlsrv_close($conn_id); + } + +} + + + +/* End of file mssql_driver.php */ +/* Location: ./system/database/drivers/mssql/mssql_driver.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php new file mode 100644 index 0000000..cc88ec5 --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -0,0 +1,248 @@ +db->_escape_identifiers($table); + } + + // -------------------------------------------------------------------- + + /** + * Create Table + * + * @access private + * @param string the table name + * @param array the fields + * @param mixed primary key(s) + * @param mixed key(s) + * @param boolean should 'IF NOT EXISTS' be added to the SQL + * @return bool + */ + function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists) + { + $sql = 'CREATE TABLE '; + + if ($if_not_exists === TRUE) + { + $sql .= 'IF NOT EXISTS '; + } + + $sql .= $this->db->_escape_identifiers($table)." ("; + $current_field_count = 0; + + foreach ($fields as $field=>$attributes) + { + // Numeric field names aren't allowed in databases, so if the key is + // numeric, we know it was assigned by PHP and the developer manually + // entered the field information, so we'll simply add it to the list + if (is_numeric($field)) + { + $sql .= "\n\t$attributes"; + } + else + { + $attributes = array_change_key_case($attributes, CASE_UPPER); + + $sql .= "\n\t".$this->db->_protect_identifiers($field); + + $sql .= ' '.$attributes['TYPE']; + + if (array_key_exists('CONSTRAINT', $attributes)) + { + $sql .= '('.$attributes['CONSTRAINT'].')'; + } + + if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE) + { + $sql .= ' UNSIGNED'; + } + + if (array_key_exists('DEFAULT', $attributes)) + { + $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\''; + } + + if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE) + { + $sql .= ' AUTO_INCREMENT'; + } + } + + // don't add a comma on the end of the last field + if (++$current_field_count < count($fields)) + { + $sql .= ','; + } + } + + if (count($primary_keys) > 0) + { + $primary_keys = $this->db->_protect_identifiers($primary_keys); + $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")"; + } + + if (is_array($keys) && count($keys) > 0) + { + foreach ($keys as $key) + { + if (is_array($key)) + { + $key = $this->db->_protect_identifiers($key); + } + else + { + $key = array($this->db->_protect_identifiers($key)); + } + + $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")"; + } + } + + $sql .= "\n)"; + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Alter table query + * + * Generates a platform-specific query so that a table can be altered + * Called by add_column(), drop_column(), and column_alter(), + * + * @access private + * @param string the ALTER type (ADD, DROP, CHANGE) + * @param string the column name + * @param string the table name + * @param string the column definition + * @param string the default value + * @param boolean should 'NOT NULL' be added + * @param string the field after which we should add the new field + * @return object + */ + function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '') + { + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name); + + // DROP has everything it needs now. + if ($alter_type == 'DROP') + { + return $sql; + } + + $sql .= " $column_definition"; + + if ($default_value != '') + { + $sql .= " DEFAULT \"$default_value\""; + } + + if ($null === NULL) + { + $sql .= ' NULL'; + } + else + { + $sql .= ' NOT NULL'; + } + + if ($after_field != '') + { + $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field); + } + + return $sql; + + } + + // -------------------------------------------------------------------- + + /** + * Rename a table + * + * Generates a platform-specific query so that a table can be renamed + * + * @access private + * @param string the old table name + * @param string the new table name + * @return string + */ + function _rename_table($table_name, $new_table_name) + { + // I think this syntax will work, but can find little documentation on renaming tables in MSSQL + $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name); + return $sql; + } + +} + +/* End of file mssql_forge.php */ +/* Location: ./system/database/drivers/mssql/mssql_forge.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php new file mode 100644 index 0000000..bf0abd1 --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_result.php @@ -0,0 +1,169 @@ +result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @access public + * @return integer + */ + function num_fields() + { + return @sqlsrv_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @access public + * @return array + */ + function list_fields() + { + $field_names = array(); + foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field) + { + $field_names[] = $field['Name']; + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @access public + * @return array + */ + function field_data() + { + $retval = array(); + foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field) + { + $F = new stdClass(); + $F->name = $field['Name']; + $F->type = $field['Type']; + $F->max_length = $field['Size']; + $F->primary_key = 0; + $F->default = ''; + + $retval[] = $F; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Free the result + * + * @return null + */ + function free_result() + { + if (is_resource($this->result_id)) + { + sqlsrv_free_stmt($this->result_id); + $this->result_id = FALSE; + } + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero + * + * @access private + * @return array + */ + function _data_seek($n = 0) + { + // Not implemented + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @access private + * @return array + */ + function _fetch_assoc() + { + return sqlsrv_fetch_array($this->result_id, SQLSRV_FETCH_ASSOC); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @access private + * @return object + */ + function _fetch_object() + { + return sqlsrv_fetch_object($this->result_id); + } + +} + + +/* End of file mssql_result.php */ +/* Location: ./system/database/drivers/mssql/mssql_result.php */ \ No newline at end of file diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php new file mode 100644 index 0000000..13a1850 --- /dev/null +++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php @@ -0,0 +1,88 @@ +db->display_error('db_unsuported_feature'); + } + +} + +/* End of file mssql_utility.php */ +/* Location: ./system/database/drivers/mssql/mssql_utility.php */ \ No newline at end of file diff --git a/system/database/index.html b/system/database/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/database/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/fonts/index.html b/system/fonts/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/fonts/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/fonts/texb.ttf b/system/fonts/texb.ttf new file mode 100644 index 0000000000000000000000000000000000000000..383c88b86b7c17e2e284732af48b2bfc359647ae GIT binary patch literal 143830 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 z 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 n`i '', 'img_path' => '', 'img_url' => '', 'img_width' => '150', 'img_height' => '30', 'font_path' => '', 'expiration' => 7200); + + foreach ($defaults as $key => $val) + { + if ( ! is_array($data)) + { + if ( ! isset($$key) OR $$key == '') + { + $$key = $val; + } + } + else + { + $$key = ( ! isset($data[$key])) ? $val : $data[$key]; + } + } + + if ($img_path == '' OR $img_url == '') + { + return FALSE; + } + + if ( ! @is_dir($img_path)) + { + return FALSE; + } + + if ( ! is_writable($img_path)) + { + return FALSE; + } + + if ( ! extension_loaded('gd')) + { + return FALSE; + } + + // ----------------------------------- + // Remove old images + // ----------------------------------- + + list($usec, $sec) = explode(" ", microtime()); + $now = ((float)$usec + (float)$sec); + + $current_dir = @opendir($img_path); + + while ($filename = @readdir($current_dir)) + { + if ($filename != "." and $filename != ".." and $filename != "index.html") + { + $name = str_replace(".jpg", "", $filename); + + if (($name + $expiration) < $now) + { + @unlink($img_path.$filename); + } + } + } + + @closedir($current_dir); + + // ----------------------------------- + // Do we have a "word" yet? + // ----------------------------------- + + if ($word == '') + { + $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + $str = ''; + for ($i = 0; $i < 8; $i++) + { + $str .= substr($pool, mt_rand(0, strlen($pool) -1), 1); + } + + $word = $str; + } + + // ----------------------------------- + // Determine angle and position + // ----------------------------------- + + $length = strlen($word); + $angle = ($length >= 6) ? rand(-($length-6), ($length-6)) : 0; + $x_axis = rand(6, (360/$length)-16); + $y_axis = ($angle >= 0 ) ? rand($img_height, $img_width) : rand(6, $img_height); + + // ----------------------------------- + // Create image + // ----------------------------------- + + // PHP.net recommends imagecreatetruecolor(), but it isn't always available + if (function_exists('imagecreatetruecolor')) + { + $im = imagecreatetruecolor($img_width, $img_height); + } + else + { + $im = imagecreate($img_width, $img_height); + } + + // ----------------------------------- + // Assign colors + // ----------------------------------- + + $bg_color = imagecolorallocate ($im, 255, 255, 255); + $border_color = imagecolorallocate ($im, 153, 102, 102); + $text_color = imagecolorallocate ($im, 204, 153, 153); + $grid_color = imagecolorallocate($im, 255, 182, 182); + $shadow_color = imagecolorallocate($im, 255, 240, 240); + + // ----------------------------------- + // Create the rectangle + // ----------------------------------- + + ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $bg_color); + + // ----------------------------------- + // Create the spiral pattern + // ----------------------------------- + + $theta = 1; + $thetac = 7; + $radius = 16; + $circles = 20; + $points = 32; + + for ($i = 0; $i < ($circles * $points) - 1; $i++) + { + $theta = $theta + $thetac; + $rad = $radius * ($i / $points ); + $x = ($rad * cos($theta)) + $x_axis; + $y = ($rad * sin($theta)) + $y_axis; + $theta = $theta + $thetac; + $rad1 = $radius * (($i + 1) / $points); + $x1 = ($rad1 * cos($theta)) + $x_axis; + $y1 = ($rad1 * sin($theta )) + $y_axis; + imageline($im, $x, $y, $x1, $y1, $grid_color); + $theta = $theta - $thetac; + } + + // ----------------------------------- + // Write the text + // ----------------------------------- + + $use_font = ($font_path != '' AND file_exists($font_path) AND function_exists('imagettftext')) ? TRUE : FALSE; + + if ($use_font == FALSE) + { + $font_size = 5; + $x = rand(0, $img_width/($length/3)); + $y = 0; + } + else + { + $font_size = 16; + $x = rand(0, $img_width/($length/1.5)); + $y = $font_size+2; + } + + for ($i = 0; $i < strlen($word); $i++) + { + if ($use_font == FALSE) + { + $y = rand(0 , $img_height/2); + imagestring($im, $font_size, $x, $y, substr($word, $i, 1), $text_color); + $x += ($font_size*2); + } + else + { + $y = rand($img_height/2, $img_height-3); + imagettftext($im, $font_size, $angle, $x, $y, $text_color, $font_path, substr($word, $i, 1)); + $x += $font_size; + } + } + + + // ----------------------------------- + // Create the border + // ----------------------------------- + + imagerectangle($im, 0, 0, $img_width-1, $img_height-1, $border_color); + + // ----------------------------------- + // Generate the image + // ----------------------------------- + + $img_name = $now.'.jpg'; + + ImageJPEG($im, $img_path.$img_name); + + $img = "\""; + + ImageDestroy($im); + + return array('word' => $word, 'time' => $now, 'image' => $img); + } +} + +// ------------------------------------------------------------------------ + +/* End of file captcha_helper.php */ +/* Location: ./system/heleprs/captcha_helper.php */ \ No newline at end of file diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php new file mode 100644 index 0000000..7cee028 --- /dev/null +++ b/system/helpers/cookie_helper.php @@ -0,0 +1,103 @@ +input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure); + } +} + +// -------------------------------------------------------------------- + +/** + * Fetch an item from the COOKIE array + * + * @access public + * @param string + * @param bool + * @return mixed + */ +if ( ! function_exists('get_cookie')) +{ + function get_cookie($index = '', $xss_clean = FALSE) + { + $CI =& get_instance(); + + $prefix = ''; + + if ( ! isset($_COOKIE[$index]) && config_item('cookie_prefix') != '') + { + $prefix = config_item('cookie_prefix'); + } + + return $CI->input->cookie($prefix.$index, $xss_clean); + } +} + +// -------------------------------------------------------------------- + +/** + * Delete a COOKIE + * + * @param mixed + * @param string the cookie domain. Usually: .yourdomain.com + * @param string the cookie path + * @param string the cookie prefix + * @return void + */ +if ( ! function_exists('delete_cookie')) +{ + function delete_cookie($name = '', $domain = '', $path = '/', $prefix = '') + { + set_cookie($name, '', '', $domain, $path, $prefix); + } +} + + +/* End of file cookie_helper.php */ +/* Location: ./system/helpers/cookie_helper.php */ \ No newline at end of file diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php new file mode 100644 index 0000000..0aeb7fa --- /dev/null +++ b/system/helpers/date_helper.php @@ -0,0 +1,611 @@ +config->item('time_reference')) == 'gmt') + { + $now = time(); + $system_time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now)); + + if (strlen($system_time) < 10) + { + $system_time = time(); + log_message('error', 'The Date class could not set a proper GMT timestamp so the local time() value was used.'); + } + + return $system_time; + } + else + { + return time(); + } + } +} + +// ------------------------------------------------------------------------ + +/** + * Convert MySQL Style Datecodes + * + * This function is identical to PHPs date() function, + * except that it allows date codes to be formatted using + * the MySQL style, where each code letter is preceded + * with a percent sign: %Y %m %d etc... + * + * The benefit of doing dates this way is that you don't + * have to worry about escaping your text letters that + * match the date codes. + * + * @access public + * @param string + * @param integer + * @return integer + */ +if ( ! function_exists('mdate')) +{ + function mdate($datestr = '', $time = '') + { + if ($datestr == '') + return ''; + + if ($time == '') + $time = now(); + + $datestr = str_replace('%\\', '', preg_replace("/([a-z]+?){1}/i", "\\\\\\1", $datestr)); + return date($datestr, $time); + } +} + +// ------------------------------------------------------------------------ + +/** + * Standard Date + * + * Returns a date formatted according to the submitted standard. + * + * @access public + * @param string the chosen format + * @param integer Unix timestamp + * @return string + */ +if ( ! function_exists('standard_date')) +{ + function standard_date($fmt = 'DATE_RFC822', $time = '') + { + $formats = array( + 'DATE_ATOM' => '%Y-%m-%dT%H:%i:%s%Q', + 'DATE_COOKIE' => '%l, %d-%M-%y %H:%i:%s UTC', + 'DATE_ISO8601' => '%Y-%m-%dT%H:%i:%s%Q', + 'DATE_RFC822' => '%D, %d %M %y %H:%i:%s %O', + 'DATE_RFC850' => '%l, %d-%M-%y %H:%i:%s UTC', + 'DATE_RFC1036' => '%D, %d %M %y %H:%i:%s %O', + 'DATE_RFC1123' => '%D, %d %M %Y %H:%i:%s %O', + 'DATE_RSS' => '%D, %d %M %Y %H:%i:%s %O', + 'DATE_W3C' => '%Y-%m-%dT%H:%i:%s%Q' + ); + + if ( ! isset($formats[$fmt])) + { + return FALSE; + } + + return mdate($formats[$fmt], $time); + } +} + +// ------------------------------------------------------------------------ + +/** + * Timespan + * + * Returns a span of seconds in this format: + * 10 days 14 hours 36 minutes 47 seconds + * + * @access public + * @param integer a number of seconds + * @param integer Unix timestamp + * @return integer + */ +if ( ! function_exists('timespan')) +{ + function timespan($seconds = 1, $time = '') + { + $CI =& get_instance(); + $CI->lang->load('date'); + + if ( ! is_numeric($seconds)) + { + $seconds = 1; + } + + if ( ! is_numeric($time)) + { + $time = time(); + } + + if ($time <= $seconds) + { + $seconds = 1; + } + else + { + $seconds = $time - $seconds; + } + + $str = ''; + $years = floor($seconds / 31536000); + + if ($years > 0) + { + $str .= $years.' '.$CI->lang->line((($years > 1) ? 'date_years' : 'date_year')).', '; + } + + $seconds -= $years * 31536000; + $months = floor($seconds / 2628000); + + if ($years > 0 OR $months > 0) + { + if ($months > 0) + { + $str .= $months.' '.$CI->lang->line((($months > 1) ? 'date_months' : 'date_month')).', '; + } + + $seconds -= $months * 2628000; + } + + $weeks = floor($seconds / 604800); + + if ($years > 0 OR $months > 0 OR $weeks > 0) + { + if ($weeks > 0) + { + $str .= $weeks.' '.$CI->lang->line((($weeks > 1) ? 'date_weeks' : 'date_week')).', '; + } + + $seconds -= $weeks * 604800; + } + + $days = floor($seconds / 86400); + + if ($months > 0 OR $weeks > 0 OR $days > 0) + { + if ($days > 0) + { + $str .= $days.' '.$CI->lang->line((($days > 1) ? 'date_days' : 'date_day')).', '; + } + + $seconds -= $days * 86400; + } + + $hours = floor($seconds / 3600); + + if ($days > 0 OR $hours > 0) + { + if ($hours > 0) + { + $str .= $hours.' '.$CI->lang->line((($hours > 1) ? 'date_hours' : 'date_hour')).', '; + } + + $seconds -= $hours * 3600; + } + + $minutes = floor($seconds / 60); + + if ($days > 0 OR $hours > 0 OR $minutes > 0) + { + if ($minutes > 0) + { + $str .= $minutes.' '.$CI->lang->line((($minutes > 1) ? 'date_minutes' : 'date_minute')).', '; + } + + $seconds -= $minutes * 60; + } + + if ($str == '') + { + $str .= $seconds.' '.$CI->lang->line((($seconds > 1) ? 'date_seconds' : 'date_second')).', '; + } + + return substr(trim($str), 0, -1); + } +} + +// ------------------------------------------------------------------------ + +/** + * Number of days in a month + * + * Takes a month/year as input and returns the number of days + * for the given month/year. Takes leap years into consideration. + * + * @access public + * @param integer a numeric month + * @param integer a numeric year + * @return integer + */ +if ( ! function_exists('days_in_month')) +{ + function days_in_month($month = 0, $year = '') + { + if ($month < 1 OR $month > 12) + { + return 0; + } + + if ( ! is_numeric($year) OR strlen($year) != 4) + { + $year = date('Y'); + } + + if ($month == 2) + { + if ($year % 400 == 0 OR ($year % 4 == 0 AND $year % 100 != 0)) + { + return 29; + } + } + + $days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); + return $days_in_month[$month - 1]; + } +} + +// ------------------------------------------------------------------------ + +/** + * Converts a local Unix timestamp to GMT + * + * @access public + * @param integer Unix timestamp + * @return integer + */ +if ( ! function_exists('local_to_gmt')) +{ + function local_to_gmt($time = '') + { + if ($time == '') + $time = time(); + + return mktime( gmdate("H", $time), gmdate("i", $time), gmdate("s", $time), gmdate("m", $time), gmdate("d", $time), gmdate("Y", $time)); + } +} + +// ------------------------------------------------------------------------ + +/** + * Converts GMT time to a localized value + * + * Takes a Unix timestamp (in GMT) as input, and returns + * at the local value based on the timezone and DST setting + * submitted + * + * @access public + * @param integer Unix timestamp + * @param string timezone + * @param bool whether DST is active + * @return integer + */ +if ( ! function_exists('gmt_to_local')) +{ + function gmt_to_local($time = '', $timezone = 'UTC', $dst = FALSE) + { + if ($time == '') + { + return now(); + } + + $time += timezones($timezone) * 3600; + + if ($dst == TRUE) + { + $time += 3600; + } + + return $time; + } +} + +// ------------------------------------------------------------------------ + +/** + * Converts a MySQL Timestamp to Unix + * + * @access public + * @param integer Unix timestamp + * @return integer + */ +if ( ! function_exists('mysql_to_unix')) +{ + function mysql_to_unix($time = '') + { + // We'll remove certain characters for backward compatibility + // since the formatting changed with MySQL 4.1 + // YYYY-MM-DD HH:MM:SS + + $time = str_replace('-', '', $time); + $time = str_replace(':', '', $time); + $time = str_replace(' ', '', $time); + + // YYYYMMDDHHMMSS + return mktime( + substr($time, 8, 2), + substr($time, 10, 2), + substr($time, 12, 2), + substr($time, 4, 2), + substr($time, 6, 2), + substr($time, 0, 4) + ); + } +} + +// ------------------------------------------------------------------------ + +/** + * Unix to "Human" + * + * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM + * + * @access public + * @param integer Unix timestamp + * @param bool whether to show seconds + * @param string format: us or euro + * @return string + */ +if ( ! function_exists('unix_to_human')) +{ + function unix_to_human($time = '', $seconds = FALSE, $fmt = 'us') + { + $r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' '; + + if ($fmt == 'us') + { + $r .= date('h', $time).':'.date('i', $time); + } + else + { + $r .= date('H', $time).':'.date('i', $time); + } + + if ($seconds) + { + $r .= ':'.date('s', $time); + } + + if ($fmt == 'us') + { + $r .= ' '.date('A', $time); + } + + return $r; + } +} + +// ------------------------------------------------------------------------ + +/** + * Convert "human" date to GMT + * + * Reverses the above process + * + * @access public + * @param string format: us or euro + * @return integer + */ +if ( ! function_exists('human_to_unix')) +{ + function human_to_unix($datestr = '') + { + if ($datestr == '') + { + return FALSE; + } + + $datestr = trim($datestr); + $datestr = preg_replace("/\040+/", ' ', $datestr); + + if ( ! preg_match('/^[0-9]{2,4}\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr)) + { + return FALSE; + } + + $split = explode(' ', $datestr); + + $ex = explode("-", $split['0']); + + $year = (strlen($ex['0']) == 2) ? '20'.$ex['0'] : $ex['0']; + $month = (strlen($ex['1']) == 1) ? '0'.$ex['1'] : $ex['1']; + $day = (strlen($ex['2']) == 1) ? '0'.$ex['2'] : $ex['2']; + + $ex = explode(":", $split['1']); + + $hour = (strlen($ex['0']) == 1) ? '0'.$ex['0'] : $ex['0']; + $min = (strlen($ex['1']) == 1) ? '0'.$ex['1'] : $ex['1']; + + if (isset($ex['2']) && preg_match('/[0-9]{1,2}/', $ex['2'])) + { + $sec = (strlen($ex['2']) == 1) ? '0'.$ex['2'] : $ex['2']; + } + else + { + // Unless specified, seconds get set to zero. + $sec = '00'; + } + + if (isset($split['2'])) + { + $ampm = strtolower($split['2']); + + if (substr($ampm, 0, 1) == 'p' AND $hour < 12) + $hour = $hour + 12; + + if (substr($ampm, 0, 1) == 'a' AND $hour == 12) + $hour = '00'; + + if (strlen($hour) == 1) + $hour = '0'.$hour; + } + + return mktime($hour, $min, $sec, $month, $day, $year); + } +} + +// ------------------------------------------------------------------------ + +/** + * Timezone Menu + * + * Generates a drop-down menu of timezones. + * + * @access public + * @param string timezone + * @param string classname + * @param string menu name + * @return string + */ +if ( ! function_exists('timezone_menu')) +{ + function timezone_menu($default = 'UTC', $class = "", $name = 'timezones') + { + $CI =& get_instance(); + $CI->lang->load('date'); + + if ($default == 'GMT') + $default = 'UTC'; + + $menu = '"; + + return $menu; + } +} + +// ------------------------------------------------------------------------ + +/** + * Timezones + * + * Returns an array of timezones. This is a helper function + * for various other ones in this library + * + * @access public + * @param string timezone + * @return string + */ +if ( ! function_exists('timezones')) +{ + function timezones($tz = '') + { + // Note: Don't change the order of these even though + // some items appear to be in the wrong order + + $zones = array( + 'UM12' => -12, + 'UM11' => -11, + 'UM10' => -10, + 'UM95' => -9.5, + 'UM9' => -9, + 'UM8' => -8, + 'UM7' => -7, + 'UM6' => -6, + 'UM5' => -5, + 'UM45' => -4.5, + 'UM4' => -4, + 'UM35' => -3.5, + 'UM3' => -3, + 'UM2' => -2, + 'UM1' => -1, + 'UTC' => 0, + 'UP1' => +1, + 'UP2' => +2, + 'UP3' => +3, + 'UP35' => +3.5, + 'UP4' => +4, + 'UP45' => +4.5, + 'UP5' => +5, + 'UP55' => +5.5, + 'UP575' => +5.75, + 'UP6' => +6, + 'UP65' => +6.5, + 'UP7' => +7, + 'UP8' => +8, + 'UP875' => +8.75, + 'UP9' => +9, + 'UP95' => +9.5, + 'UP10' => +10, + 'UP105' => +10.5, + 'UP11' => +11, + 'UP115' => +11.5, + 'UP12' => +12, + 'UP1275' => +12.75, + 'UP13' => +13, + 'UP14' => +14 + ); + + if ($tz == '') + { + return $zones; + } + + if ($tz == 'GMT') + $tz = 'UTC'; + + return ( ! isset($zones[$tz])) ? 0 : $zones[$tz]; + } +} + + +/* End of file date_helper.php */ +/* Location: ./system/helpers/date_helper.php */ \ No newline at end of file diff --git a/system/helpers/directory_helper.php b/system/helpers/directory_helper.php new file mode 100644 index 0000000..38347fa --- /dev/null +++ b/system/helpers/directory_helper.php @@ -0,0 +1,80 @@ + 0) && @is_dir($source_dir.$file)) + { + $filedata[$file] = directory_map($source_dir.$file.DIRECTORY_SEPARATOR, $new_depth, $hidden); + } + else + { + $filedata[] = $file; + } + } + + closedir($fp); + return $filedata; + } + + return FALSE; + } +} + + +/* End of file directory_helper.php */ +/* Location: ./system/helpers/directory_helper.php */ \ No newline at end of file diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php new file mode 100644 index 0000000..1145688 --- /dev/null +++ b/system/helpers/download_helper.php @@ -0,0 +1,107 @@ + 0) + { + $data =& fread($fp, filesize($file)); + } + + flock($fp, LOCK_UN); + fclose($fp); + + return $data; + } +} + +// ------------------------------------------------------------------------ + +/** + * Write File + * + * Writes data to the file specified in the path. + * Creates a new file if non-existent. + * + * @access public + * @param string path to file + * @param string file data + * @return bool + */ +if ( ! function_exists('write_file')) +{ + function write_file($path, $data, $mode = FOPEN_WRITE_CREATE_DESTRUCTIVE) + { + if ( ! $fp = @fopen($path, $mode)) + { + return FALSE; + } + + flock($fp, LOCK_EX); + fwrite($fp, $data); + flock($fp, LOCK_UN); + fclose($fp); + + return TRUE; + } +} + +// ------------------------------------------------------------------------ + +/** + * Delete Files + * + * Deletes all files contained in the supplied directory path. + * Files must be writable or owned by the system in order to be deleted. + * If the second parameter is set to TRUE, any directories contained + * within the supplied base directory will be nuked as well. + * + * @access public + * @param string path to file + * @param bool whether to delete any directories found in the path + * @return bool + */ +if ( ! function_exists('delete_files')) +{ + function delete_files($path, $del_dir = FALSE, $level = 0) + { + // Trim the trailing slash + $path = rtrim($path, DIRECTORY_SEPARATOR); + + if ( ! $current_dir = @opendir($path)) + { + return FALSE; + } + + while (FALSE !== ($filename = @readdir($current_dir))) + { + if ($filename != "." and $filename != "..") + { + if (is_dir($path.DIRECTORY_SEPARATOR.$filename)) + { + // Ignore empty folders + if (substr($filename, 0, 1) != '.') + { + delete_files($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $level + 1); + } + } + else + { + unlink($path.DIRECTORY_SEPARATOR.$filename); + } + } + } + @closedir($current_dir); + + if ($del_dir == TRUE AND $level > 0) + { + return @rmdir($path); + } + + return TRUE; + } +} + +// ------------------------------------------------------------------------ + +/** + * Get Filenames + * + * Reads the specified directory and builds an array containing the filenames. + * Any sub-folders contained within the specified path are read as well. + * + * @access public + * @param string path to source + * @param bool whether to include the path as part of the filename + * @param bool internal variable to determine recursion status - do not use in calls + * @return array + */ +if ( ! function_exists('get_filenames')) +{ + function get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE) + { + static $_filedata = array(); + + if ($fp = @opendir($source_dir)) + { + // reset the array and make sure $source_dir has a trailing slash on the initial call + if ($_recursion === FALSE) + { + $_filedata = array(); + $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; + } + + while (FALSE !== ($file = readdir($fp))) + { + if (@is_dir($source_dir.$file) && strncmp($file, '.', 1) !== 0) + { + get_filenames($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE); + } + elseif (strncmp($file, '.', 1) !== 0) + { + $_filedata[] = ($include_path == TRUE) ? $source_dir.$file : $file; + } + } + return $_filedata; + } + else + { + return FALSE; + } + } +} + +// -------------------------------------------------------------------- + +/** + * Get Directory File Information + * + * Reads the specified directory and builds an array containing the filenames, + * filesize, dates, and permissions + * + * Any sub-folders contained within the specified path are read as well. + * + * @access public + * @param string path to source + * @param bool Look only at the top level directory specified? + * @param bool internal variable to determine recursion status - do not use in calls + * @return array + */ +if ( ! function_exists('get_dir_file_info')) +{ + function get_dir_file_info($source_dir, $top_level_only = TRUE, $_recursion = FALSE) + { + static $_filedata = array(); + $relative_path = $source_dir; + + if ($fp = @opendir($source_dir)) + { + // reset the array and make sure $source_dir has a trailing slash on the initial call + if ($_recursion === FALSE) + { + $_filedata = array(); + $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; + } + + // foreach (scandir($source_dir, 1) as $file) // In addition to being PHP5+, scandir() is simply not as fast + while (FALSE !== ($file = readdir($fp))) + { + if (@is_dir($source_dir.$file) AND strncmp($file, '.', 1) !== 0 AND $top_level_only === FALSE) + { + get_dir_file_info($source_dir.$file.DIRECTORY_SEPARATOR, $top_level_only, TRUE); + } + elseif (strncmp($file, '.', 1) !== 0) + { + $_filedata[$file] = get_file_info($source_dir.$file); + $_filedata[$file]['relative_path'] = $relative_path; + } + } + + return $_filedata; + } + else + { + return FALSE; + } + } +} + +// -------------------------------------------------------------------- + +/** +* Get File Info +* +* Given a file and path, returns the name, path, size, date modified +* Second parameter allows you to explicitly declare what information you want returned +* Options are: name, server_path, size, date, readable, writable, executable, fileperms +* Returns FALSE if the file cannot be found. +* +* @access public +* @param string path to file +* @param mixed array or comma separated string of information returned +* @return array +*/ +if ( ! function_exists('get_file_info')) +{ + function get_file_info($file, $returned_values = array('name', 'server_path', 'size', 'date')) + { + + if ( ! file_exists($file)) + { + return FALSE; + } + + if (is_string($returned_values)) + { + $returned_values = explode(',', $returned_values); + } + + foreach ($returned_values as $key) + { + switch ($key) + { + case 'name': + $fileinfo['name'] = substr(strrchr($file, DIRECTORY_SEPARATOR), 1); + break; + case 'server_path': + $fileinfo['server_path'] = $file; + break; + case 'size': + $fileinfo['size'] = filesize($file); + break; + case 'date': + $fileinfo['date'] = filemtime($file); + break; + case 'readable': + $fileinfo['readable'] = is_readable($file); + break; + case 'writable': + // There are known problems using is_weritable on IIS. It may not be reliable - consider fileperms() + $fileinfo['writable'] = is_writable($file); + break; + case 'executable': + $fileinfo['executable'] = is_executable($file); + break; + case 'fileperms': + $fileinfo['fileperms'] = fileperms($file); + break; + } + } + + return $fileinfo; + } +} + +// -------------------------------------------------------------------- + +/** + * Get Mime by Extension + * + * Translates a file extension into a mime type based on config/mimes.php. + * Returns FALSE if it can't determine the type, or open the mime config file + * + * Note: this is NOT an accurate way of determining file mime types, and is here strictly as a convenience + * It should NOT be trusted, and should certainly NOT be used for security + * + * @access public + * @param string path to file + * @return mixed + */ +if ( ! function_exists('get_mime_by_extension')) +{ + function get_mime_by_extension($file) + { + $extension = strtolower(substr(strrchr($file, '.'), 1)); + + global $mimes; + + if ( ! is_array($mimes)) + { + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'); + } + elseif (is_file(APPPATH.'config/mimes.php')) + { + include(APPPATH.'config/mimes.php'); + } + + if ( ! is_array($mimes)) + { + return FALSE; + } + } + + if (array_key_exists($extension, $mimes)) + { + if (is_array($mimes[$extension])) + { + // Multiple mime types, just give the first one + return current($mimes[$extension]); + } + else + { + return $mimes[$extension]; + } + } + else + { + return FALSE; + } + } +} + +// -------------------------------------------------------------------- + +/** + * Symbolic Permissions + * + * Takes a numeric value representing a file's permissions and returns + * standard symbolic notation representing that value + * + * @access public + * @param int + * @return string + */ +if ( ! function_exists('symbolic_permissions')) +{ + function symbolic_permissions($perms) + { + if (($perms & 0xC000) == 0xC000) + { + $symbolic = 's'; // Socket + } + elseif (($perms & 0xA000) == 0xA000) + { + $symbolic = 'l'; // Symbolic Link + } + elseif (($perms & 0x8000) == 0x8000) + { + $symbolic = '-'; // Regular + } + elseif (($perms & 0x6000) == 0x6000) + { + $symbolic = 'b'; // Block special + } + elseif (($perms & 0x4000) == 0x4000) + { + $symbolic = 'd'; // Directory + } + elseif (($perms & 0x2000) == 0x2000) + { + $symbolic = 'c'; // Character special + } + elseif (($perms & 0x1000) == 0x1000) + { + $symbolic = 'p'; // FIFO pipe + } + else + { + $symbolic = 'u'; // Unknown + } + + // Owner + $symbolic .= (($perms & 0x0100) ? 'r' : '-'); + $symbolic .= (($perms & 0x0080) ? 'w' : '-'); + $symbolic .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-')); + + // Group + $symbolic .= (($perms & 0x0020) ? 'r' : '-'); + $symbolic .= (($perms & 0x0010) ? 'w' : '-'); + $symbolic .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-')); + + // World + $symbolic .= (($perms & 0x0004) ? 'r' : '-'); + $symbolic .= (($perms & 0x0002) ? 'w' : '-'); + $symbolic .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-')); + + return $symbolic; + } +} + +// -------------------------------------------------------------------- + +/** + * Octal Permissions + * + * Takes a numeric value representing a file's permissions and returns + * a three character string representing the file's octal permissions + * + * @access public + * @param int + * @return string + */ +if ( ! function_exists('octal_permissions')) +{ + function octal_permissions($perms) + { + return substr(sprintf('%o', $perms), -3); + } +} + + +/* End of file file_helper.php */ +/* Location: ./system/helpers/file_helper.php */ \ No newline at end of file diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php new file mode 100644 index 0000000..8733ae0 --- /dev/null +++ b/system/helpers/form_helper.php @@ -0,0 +1,1054 @@ +config->site_url($action); + } + + // If no action is provided then set to the current url + $action OR $action = $CI->config->site_url($CI->uri->uri_string()); + + $form = '
    config->item('csrf_protection') === TRUE AND ! (strpos($action, $CI->config->base_url()) === FALSE OR strpos($form, 'method="get"'))) + { + $hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash(); + } + + if (is_array($hidden) AND count($hidden) > 0) + { + $form .= sprintf("
    %s
    ", form_hidden($hidden)); + } + + return $form; + } +} + +// ------------------------------------------------------------------------ + +/** + * Form Declaration - Multipart type + * + * Creates the opening portion of the form, but with "multipart/form-data". + * + * @access public + * @param string the URI segments of the form destination + * @param array a key/value pair of attributes + * @param array a key/value pair hidden data + * @return string + */ +if ( ! function_exists('form_open_multipart')) +{ + function form_open_multipart($action = '', $attributes = array(), $hidden = array()) + { + if (is_string($attributes)) + { + $attributes .= ' enctype="multipart/form-data"'; + } + else + { + $attributes['enctype'] = 'multipart/form-data'; + } + + return form_open($action, $attributes, $hidden); + } +} + +// ------------------------------------------------------------------------ + +/** + * Hidden Input Field + * + * Generates hidden fields. You can pass a simple key/value string or an associative + * array with multiple values. + * + * @access public + * @param mixed + * @param string + * @return string + */ +if ( ! function_exists('form_hidden')) +{ + function form_hidden($name, $value = '', $recursing = FALSE) + { + static $form; + + if ($recursing === FALSE) + { + $form = "\n"; + } + + if (is_array($name)) + { + foreach ($name as $key => $val) + { + form_hidden($key, $val, TRUE); + } + return $form; + } + + if ( ! is_array($value)) + { + $form .= ''."\n"; + } + else + { + foreach ($value as $k => $v) + { + $k = (is_int($k)) ? '' : $k; + form_hidden($name.'['.$k.']', $v, TRUE); + } + } + + return $form; + } +} + +// ------------------------------------------------------------------------ + +/** + * Text Input Field + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_input')) +{ + function form_input($data = '', $value = '', $extra = '') + { + $defaults = array('type' => 'text', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value); + + return ""; + } +} + +// ------------------------------------------------------------------------ + +/** + * Password Field + * + * Identical to the input function but adds the "password" type + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_password')) +{ + function form_password($data = '', $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'password'; + return form_input($data, $value, $extra); + } +} + +// ------------------------------------------------------------------------ + +/** + * Upload Field + * + * Identical to the input function but adds the "file" type + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_upload')) +{ + function form_upload($data = '', $value = '', $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'file'; + return form_input($data, $value, $extra); + } +} + +// ------------------------------------------------------------------------ + +/** + * Textarea field + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_textarea')) +{ + function form_textarea($data = '', $value = '', $extra = '') + { + $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '40', 'rows' => '10'); + + if ( ! is_array($data) OR ! isset($data['value'])) + { + $val = $value; + } + else + { + $val = $data['value']; + unset($data['value']); // textareas don't use the value attribute + } + + $name = (is_array($data)) ? $data['name'] : $data; + return ""; + } +} + +// ------------------------------------------------------------------------ + +/** + * Multi-select menu + * + * @access public + * @param string + * @param array + * @param mixed + * @param string + * @return type + */ +if ( ! function_exists('form_multiselect')) +{ + function form_multiselect($name = '', $options = array(), $selected = array(), $extra = '') + { + if ( ! strpos($extra, 'multiple')) + { + $extra .= ' multiple="multiple"'; + } + + return form_dropdown($name, $options, $selected, $extra); + } +} + +// -------------------------------------------------------------------- + +/** + * Drop-down Menu + * + * @access public + * @param string + * @param array + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_dropdown')) +{ + function form_dropdown($name = '', $options = array(), $selected = array(), $extra = '') + { + if ( ! is_array($selected)) + { + $selected = array($selected); + } + + // If no selected state was submitted we will attempt to set it automatically + if (count($selected) === 0) + { + // If the form name appears in the $_POST array we have a winner! + if (isset($_POST[$name])) + { + $selected = array($_POST[$name]); + } + } + + if ($extra != '') $extra = ' '.$extra; + + $multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : ''; + + $form = ''; + + return $form; + } +} + +// ------------------------------------------------------------------------ + +/** + * Checkbox Field + * + * @access public + * @param mixed + * @param string + * @param bool + * @param string + * @return string + */ +if ( ! function_exists('form_checkbox')) +{ + function form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '') + { + $defaults = array('type' => 'checkbox', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value); + + if (is_array($data) AND array_key_exists('checked', $data)) + { + $checked = $data['checked']; + + if ($checked == FALSE) + { + unset($data['checked']); + } + else + { + $data['checked'] = 'checked'; + } + } + + if ($checked == TRUE) + { + $defaults['checked'] = 'checked'; + } + else + { + unset($defaults['checked']); + } + + return ""; + } +} + +// ------------------------------------------------------------------------ + +/** + * Radio Button + * + * @access public + * @param mixed + * @param string + * @param bool + * @param string + * @return string + */ +if ( ! function_exists('form_radio')) +{ + function form_radio($data = '', $value = '', $checked = FALSE, $extra = '') + { + if ( ! is_array($data)) + { + $data = array('name' => $data); + } + + $data['type'] = 'radio'; + return form_checkbox($data, $value, $checked, $extra); + } +} + +// ------------------------------------------------------------------------ + +/** + * Submit Button + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_submit')) +{ + function form_submit($data = '', $value = '', $extra = '') + { + $defaults = array('type' => 'submit', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value); + + return ""; + } +} + +// ------------------------------------------------------------------------ + +/** + * Reset Button + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_reset')) +{ + function form_reset($data = '', $value = '', $extra = '') + { + $defaults = array('type' => 'reset', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value); + + return ""; + } +} + +// ------------------------------------------------------------------------ + +/** + * Form Button + * + * @access public + * @param mixed + * @param string + * @param string + * @return string + */ +if ( ! function_exists('form_button')) +{ + function form_button($data = '', $content = '', $extra = '') + { + $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'type' => 'button'); + + if ( is_array($data) AND isset($data['content'])) + { + $content = $data['content']; + unset($data['content']); // content is not an attribute + } + + return ""; + } +} + +// ------------------------------------------------------------------------ + +/** + * Form Label Tag + * + * @access public + * @param string The text to appear onscreen + * @param string The id the label applies to + * @param string Additional attributes + * @return string + */ +if ( ! function_exists('form_label')) +{ + function form_label($label_text = '', $id = '', $attributes = array()) + { + + $label = ' 0) + { + foreach ($attributes as $key => $val) + { + $label .= ' '.$key.'="'.$val.'"'; + } + } + + $label .= ">$label_text"; + + return $label; + } +} + +// ------------------------------------------------------------------------ +/** + * Fieldset Tag + * + * Used to produce
    text. To close fieldset + * use form_fieldset_close() + * + * @access public + * @param string The legend text + * @param string Additional attributes + * @return string + */ +if ( ! function_exists('form_fieldset')) +{ + function form_fieldset($legend_text = '', $attributes = array()) + { + $fieldset = "".$extra; + } +} + +// ------------------------------------------------------------------------ + +/** + * Form Close Tag + * + * @access public + * @param string + * @return string + */ +if ( ! function_exists('form_close')) +{ + function form_close($extra = '') + { + return "".$extra; + } +} + +// ------------------------------------------------------------------------ + +/** + * Form Prep + * + * Formats text so that it can be safely placed in a form field in the event it has HTML tags. + * + * @access public + * @param string + * @return string + */ +if ( ! function_exists('form_prep')) +{ + function form_prep($str = '', $field_name = '') + { + static $prepped_fields = array(); + + // if the field name is an array we do this recursively + if (is_array($str)) + { + foreach ($str as $key => $val) + { + $str[$key] = form_prep($val); + } + + return $str; + } + + if ($str === '') + { + return ''; + } + + // we've already prepped a field with this name + // @todo need to figure out a way to namespace this so + // that we know the *exact* field and not just one with + // the same name + if (isset($prepped_fields[$field_name])) + { + return $str; + } + + $str = htmlspecialchars($str); + + // In case htmlspecialchars misses these. + $str = str_replace(array("'", '"'), array("'", """), $str); + + if ($field_name != '') + { + $prepped_fields[$field_name] = $field_name; + } + + return $str; + } +} + +// ------------------------------------------------------------------------ + +/** + * Form Value + * + * Grabs a value from the POST array for the specified field so you can + * re-populate an input field or textarea. If Form Validation + * is active it retrieves the info from the validation class + * + * @access public + * @param string + * @return mixed + */ +if ( ! function_exists('set_value')) +{ + function set_value($field = '', $default = '') + { + if (FALSE === ($OBJ =& _get_validation_object())) + { + if ( ! isset($_POST[$field])) + { + return $default; + } + + return form_prep($_POST[$field], $field); + } + + return form_prep($OBJ->set_value($field, $default), $field); + } +} + +// ------------------------------------------------------------------------ + +/** + * Set Select + * + * Let's you set the selected value of a

    Ta?OVYGdWRv7rm41y7qjYOB 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%0D8I6a&+Z9@+{4A5AnNky0E-e^nL0oU_ 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 z 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%0D`vd*@C!H72XZyBDz!&tXMNcpLz;O4Ilpp(xx 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∾E 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 z zf*AW|L;W&Bz<~GDnn$~1KE?%}uB)b=4rZW>A!u4STjzYJnXB3&r+u(I*85=A7!W&| z)Y@5ffK&4>>1_m3Zw7+S^tJxX$~;9t;)`R`09P(3b(C0mMdWte6EyWR6~?+h53&5P z(^#i$+1kaO=;SHan6P3r`*W@NLz26|Ez^c9f9OY~m=D`l6|T)qPt+WYFZuz-S@*I| zOU>K_()p(h#A%G_*|i&(c+d_!(ex%WWzsSGpqCNt$hvoJO@ap+NpI@B(&ZHC?B&eY z0@VtE3!?pItDX64`{oyZx}rU>Q8m+*!z<^nvlwy}#Y%5E#RixAbJ${Aru>^NWIh8rM<3Wvwo}BE*I|`em}aR)A^`kTWvzsA&@_sgYVHjO@+OH4HM1ahG?OJ zOYXw_C@G###4fu}TwQh8kB_^vm-!_|2e(PN)^K)l-Tn7Wv#@#YGmg&R_49aJ=M0xd zmDQwEgd7D*t5wboCQg+-xzd|{UB@c<^#N|p;XZKOZTf!3Zr;|udx#y7xQ;&I_J_$f zjJ7_R%Da;6q2{_S><(?fFOoj_K?y>$Mk?Li4cC>;*R|I;Vo*~Il*G$+c}WI*34~|F z1fY#kJu4!Xzl{6AJy{(LG5?Gp&mh)qI&wff^o2>v*SJG0?{v=aZsO0L zQC{`O4hF{V)>Re^*#Ss~j()za)jTe+11=h6dYaCJVjxLRCJTq|ds! z7bR@fl!|91%!QMcg5LccUPWqIUd6{EU28)kAw>6_D5Uv{tT^C!hh_dNF0z#rhlji8 zAWw&us!H~T7#@r=>3~@ju z%Y)`M1HIyzBGmP`w&*rhjoO=aW@kM;EZJ zmNxANZ(O&EhQnSPz18`BDC}AmR@+nge&1u^f-|oh5#Zm;xLem>y4iZoO%zEyT@2M> zD-43@HZbGO008?ZLJa07#(?4U<&Gmf#F!XLyWSD!3t5$(8^j8}X#sQ7qN;TD+*otY zT%rR(o&l7Pj~_snQ0%U4Ku*JMccl>X;;87ED8w3-D@}&S`VqtUA!Bed>1`5w!H8kN zj~Jn>f7=MY*MXCv&g|v^fT4hYOe+Revzcd1GX^!#dWoaU?2_r)=mNH6lhrl1uLN5r zcdg|2lzh1o>1sc0X?*`a7mSs!?P%vrz1VSu`*%@3Rk555uQ`$IgIdwV&~@HP|NU>d zWy_rFcs4f#KifRxftg#?Ps>t-M+tv)F@MHuK3${neC*;?yQyfQ321xoEKBFDb=#I(g$;dr)=a|oYRMzF@2D_D}%v>l%NXs9aa?7 z6Swf!Gm4)e{4lcIA&f|^pQ;}4v|P%GN(kV}z$$oc6UBn9D**g^-7)!=b&wddc>Kd? z7m@CD9TjR%t5oiD!E5J5ek5g<$}krXQ9%@W)D2~hMoU8tRpp=>UVdqh73~Opm3{nj z!sZuC%)5Ai zyR)OyM&M?CphK_Sf!JTTEj8y5?B)W#lHe&_<>xv&rHaWC&dH6io0jFOUI-DHon~=O z=qsG%yz&G^;;m~Juf$zDrR~nU8#mI1?$n*_$i7XDGkc=7bdtRq| z*F0`S)&j6t_i5KvuLl3)Hb`G;|M|v;QHgWc*NO2GF6dhAj@9pt;T5rw$&y{)${Kt5 z3--orgEgi)mAb~#*m26S`mM`gH+$3&Hfcu}o{x`pVrBCPa=d5_3GTNL>WQbCRKLrv z{vkOS>MD7Y4cn8)G@Dos{E$pR3V!6rOYYt2^I46pUiz6HhKl?s_f!p>cDi%z3C@fg z>hA~@hEXVe)o0^qvhll*kAT`-3#!h%2)^X3nUp^7X6qC##9z@YAX3Vm&C+n*Wd zuFNG{y&cv~r3@FxoRJ2p<$U`+h)SwP{x@DafUL0G;Q=lBsAGFNBu?sG10EEms!Fw1Y}|)DOGvB)8Rx)f}!V zFTx6!W88SI;_*CqlJ+>FPx3HVo|JjKtBTZV{D~aEr4$D|k>AR)Pn*v1n%30{kGa^2 zM*rBoi&^wqyr8sr9~lF^Na;U4DtV}z)=3Uk7v{W$KgO5Tok>z=STg4!exug}&i*zc z!XC}7$P;DD?{sQZ@gSYJQo)`a?G`I%m)@qe$2I1ST;yI%S+lIhT~2O+Udugt4r&No zBSp3M^fpn~rN<<%86DT=4`(rM3!VeKfFUvxr(m>o$=6?y4A_E#bnnsekiy(twwL)= zed-TLX6Mjr4#)x)m0Z6%L69BBO$$w6D!h|0TeCKM;%_8#7Y8qwvPdb_kkv}ab{=MH zTjo}|#_>hr<+KVv+@`sb$*}tFlgm`cLeUKDJotbBr+26;x)i1%T!~C-e2JGkgVO9@ zx0-KjJ8Fy)tU_5l8*ba{slLpe?=dm)R@MKDdS1S&p7Ra_mb;B4F1`sv^nk{ngsflt zoYOurZ0jZ7ClnNQ5!t2^L5hF@FgY{d_!lcUFyzTgq(MI4P5~#fcQk<9Uo!8|jBLqS za@k3dm8`hMx8Aozk)Q&qR@aNWqn~KeQ^;nEn)Yp}VvRB%=(n<2#{#{*XMxO>=YOBh zFoW_Hi!dIChe-T2e2AIv!o0xm#5vujmNe6@>S*@_E(h!xfD<>+cz6l4p+7kc9@p~Y`@Lolr$^{9GWR|}>& zZ|5L#FS>*;_9*sEkbN@GVvjqL{j=-;_i}vSm9Ko&_Buv|8EOy=er3c$R|3_m6 z+=eC7urD^2AJk-8<$I^Ed9+}TP7xQijyg6dkHF`PEA66x!**Kl9Is3?I4TL$U+z;s z$qayg1;Utu=8TngFR`rHIc1W;cxvJqZ`<1n@$;cac?(pXmq1}j>O>S$^<6Gtp+A+` zZ98}NC=lqJYfw6iQw#IdPAI=C49_N-fvhpoDovkUS1bOX!|(aF%*Xc^L0IwZR* zA9r*mB9qd3$xcnPbd8G(b18hE2lBOTCoOb%f5JS9U*{;8ViroodQ-{Li^4)8?!0{| zc_s2H`rOwOM)E5WAvahDWe84Svd8$P?!#yOZrt=xF<@ z!v!_a524^r>LgB%!UCtG0lstoW*CvK=FKpkaK|At4?UduXZAQtVh}pf7FJ z@M!;@!()u*v%DuZ0DuZqc7rE)g^-XE%*+_v5B_xpZA%pY8~_22LW05SFlK3u;C9x5 zL#ZG+2lpTlv*z~) zF^?7nV5%(nEd8j_0Om!;nDA8+SeNbby{H|?p8^uF)yeb5l(b1wFS4`Q20q#6<=o*t zZuvo)CN@|B34dCI6I}UDU~b4ap$%Z|5n9e+R$C~S%x&SASBUX;6gip9GR||TbM;(_ zJH}7H1?7H>euy(B^7M28Ca%~`NJEi_9*y%j4>Bl-etZUE);&f*A<2p4!nUwv4r&#q z+?}xD7FZzP#bF%zkNzQ?J@I}i#ldNn#p>}CXEO6wtK}6}TcS$5+Zvuz$yHJbqZfw-EJR)iqfLrSR~NwhhD{t5kMU3F*V1P-|$WSMNo7(_Cw6pf1uJC)qP z7qcURXbv)UX21iJRTqIn_P{fvWQA1D-y`VqmRTiOgUVu6UoO1(?&zKXv2!Zfi^3Cz zD_69t8MpfG_z4jM z$m|nczK;}3o)s>T^(>*q>li%?t=wMLuE z_LA0u-HTHMojX2tL_BoU+j*eiV;zcianf2-o6@(0ycS3@j z3(dy{1Ol{(IL7K0hn%k@hHJ3C1XvWtwft>#fVSAe7L1Q-gIKaP)jcr>~C=-T|1svL82XBtfoJMH>3&B}=_e5x8-io;@wwZ)W zAKTCpb%+0diI7A-H~s^4@&fIDB#6_$^WP8uKj~>pI}=k6Itv$D8`fz-r~m?lkbPI@ zNKQepW*jrr?Lilzex;?DR{HpsxZBhCN_PVS@(m^#6<^qa&4vTS$MfpsuqBMZB?T9; zO^g7fTfV4rM)su<3Cc5QJ%5fwsqFIo-Y);{|NN$Z2=~9kpy^lWzi$4|<$pCzS{b?- zIvYD#I=K9Qd`ntdqLc|d06?G~007y)H#mDbyO`S2|KnMl44o`Zo$3FdC#4)+O`Sad ziwxJ=j7?3c=MXc z5uI}O+kIky0zJ@(X{=C&5f4O2YUGe3J96$CuX(eZzSpLaeq9qQGD;DNGQJhFIE##C zT4caP>nPBGXYznzk4g%;>_KhFk_|D!XfR8Dh-KP-jbVB{Gu3`=_pA3qpZQH^M)rzZugo!{RqNDU6K(+T_t6A|)`)(HwiCriNJTJX`*hx-O3VD1{sdI_ z<+;Cqcb)I+{i2fB4R18wXBgc3iU`t&3Y;lQM5x)gxM5Jwo-6wUPy)dca__ZBT_XNf zToffThwydO3Munpe7a&lgrtxpfXWYzGjg`)0iMDWV_2vVJhvO_!v9At{3|DWSZAX7 zY|KdEq&pIfbC#Ge7Z_XJDCy+2TAdPJv_~<~?4H5(rRJS>RZS&m(YnzsAjZHP-FK0~ zu~Y=m1c&+L2ms;(HQ zka@r})BsN)*}Z^htHkr*d1dRVGfO1A(R`|9O^#^#{XCbK-}LRryvZNgkkA%wO-2B2 z<3S?GGVW)=K9Pzph@{nV4i}1b+g7}dYBli~;&y*0xBl4Q0WqOx;=Drxo4J473GfzY zs}$iY+D8anns`M&H=kK5e>XRH>`=o|d2@h|*4TNytp9<_Qf>gJU?mSbO0dz<4dZBw z#+g=pqzBG7oe+3nXu`Ex?dVJEUF~rA@;j{;+7;C1Aa_cYeMO`9o4+e8cc`KK# zBw>>w4dIQ5LQ<7;ek2d0N!pTitCh7NV7HtmHU=sc%FuByqFQ^0pRg1%Zb*IZ9xquTNJlPdM0X}@e6)*M+sJuC5^{I zMl2}91f`oqM0cR`m~nf0PMvJ!5=d`=a4tr}1T!B-E9AZk$)^{>zbvi|OQn0R!*HDv zN>%5kbN_c#DGoQ_*sO}R6SE*#Cbfm|_$~=U7NkoXQks&eW>&8G?|zVP z13cDHLI{U2t_cHAp@ycjv`S^ND8knoWf)U^{2^3@-d41+Nb2Ls7ankr)S~@GbeGs< zsI7De9J>1Ifu=Pon)R#8yZ-`AzVbfso=*?)wB_~65<0wHk~vsX84hUD9p({AwH;03 ztjLNfr9V>J;1?|$wo>d^`sLgWh!5F1>kQA`utR#rexCZ!*HaAXnP9ytF_#?g%{b3k zrgu$;6#Hy}V!x!iGSfM~!}0u^GfEExJ z*}7xU$<+vhbA&CCEIB}RcF9M`xck+=(xCo}S>+Z)8cB7Me@b;l{*vYEbS8}-dh`Wn zUQG3iVXeyQlsQyX#3FS3C1EBUaEgn8BbyujO#id5ny~Z00VSBiXX?R~D-o{+4aFpl ztF-5TYQZPNNM!t1h(AuAtFNW*<%)*yr#}B-TiESiW3uFVn_49_RxL+`HVRPSTrz#44+*SlaaCUpMC_Pl&iUBINHeyl z%4w1-OYwD3)u_3z3WB@DYjB$W)2MK}-qe200Yi*Vt!gy7@GkKtMi^kv=$>gtX0|e| zSN+tQxAQd~RV{f2vw##v!@K((fbB)WluwT|ZpQ1A1%T)50>AoU(zd>N7{Pi6L!D06 z7jEUPLqRt4&`z5e=#IwOhDga1GsGwc*U9R%)G~anZ+4AR=`nSEk0@+y>H`Xt&ANn= z>ZwOL)5-xscWNm%7T7y1C;-2m^37l+kXm*V>3F1m9uSoV` zcp^q6;dS`ars!vV>S4IScWsu)sDjWV#gxq=HTB#AC5knrJR)VCZ2Ra9L`J#wftg(n zcz}*$#uv6L&1bWu9TXG z{>X1(AE4>h8BVeO-T!T3yb~tAERH>!?CL3FH(o3q%Xzqgh1w`DzR3a~3Nr@j4Q4%R zmA?Umovkz;ilyJy4fVR34C*yeRL;FP@()z}m(S3B%~?>8WoYCfW1$Kl z#Mm(zcOz}({R5Wc(-~KRW@bInj3YbmG!9AKI5Z66HRiC_uA#O z+Iq2djmvw>WKXm6nxW?E`tT2A5q#nNPegPcG>YeyW|C>PfrW?hYxP095f9|FdIn<- zG#dgGgF!z>j6kIgjnn=oA2v#)AuEj#Jz2chP-BBUFDk%Au1Ae4c1IVN~VzprgUoY5{B;$)BwoqYYKq zyL9hkCOqo02??m(ZsgS$n30So=Q@_#D9MsLDE1tv0bAyrE#c>J3HNbI@Mz>eJ|rkn zNj)iwjgQlCdo=Pa%<+FX)~1D>kC#;ELk4M10?*fY4CnvEf!IDDAG8WdEVtTzmMuA? zbDXlAPQD%S;Aa(@w(I#aO%}P$=i#p27fPZ9Pu}C;G-h=qy84cphKT^<7TIguR+tf80C=EC9l;Uhv-V47OVg)Gf~Vc<!x&uF=h~vd! z;aZ!OPK*Ojv050xxQU$&yTrOmk9Afu4EA z8p!!=f!Q37fZS@kXoA#`ZoU7662psQ*;F*t) z6PbKYgY}I`CEp!8xPnnax*yZ&k8eKWkSQu#C(Lw~GGj|&=SCP&Vf&Y6yr(;3928$8 zNIeY%(@^*$@H}NfT%Zi{>Cj@<$YsU8d3zqGdp8z~{Jo6D#KTLy0dnyQIR+%@;ahN% zK%9+o{cbBZ6 zwz3&3s=BcH?(B744%{s28^5tWmB9DCH|A(xt6^hK0aimQl)Hp}o)~?!b&*8Ewj7|p z6nf&1VkYP`eogE>P>n*6D#42VGRw&aj!2!?&sqjWaVe?ODKR)Lp_G&FQ%1L%?|2z{ zo{6sv_g#gp7;WohJB!lHh7^o&AoLkXq|ahROKWNyU%>k84P{bfG|ZXsQPDPL^S0;N zVBcdwuGQAdgQCfU46&geXR8NKHov_31s-#t_}%Hx2H!bD%|0w}g4!oy&U{AZwb)6J z(;P|6y6&a~rDnC_3tG8TA_3MS`*>P?-Ezu%hr(MV0MaB~&E^A~5J3o(8A}M-OgoT0 zEs|*Ex5xD?{o&zpLspGCyua+M9@(1`GM{f7dyLMNVW|H>*Euj}0(DzD>ab&WoOEow zv2EM7ZQHhO+qP}nwx++Dse7lU?)->zYOl5SewIRz_oycYcYFh_)?OAW<9LJSZy}m^ zAQi^bT~^{3C$$a7(I#qmg7#8?MHa%svkWiYnOTLSl;=W<+iv{<@^fLm^^2)BkhU3J zqpW)`g+z!l@hOzPCs>2^GHyhWJ#hz3Aw$HYXqAuB0X|B1Ds31nLk1_1^$5&DF8;=g zULyPrb%qIiYyNqnvo-V^mY+(qadjcgSFw5keR4nqGoyHx+QTy2lY5JBKGhtTd5v7G zkvQq3VwuwX=7*#IiOf5Gk@!SL$-w=7)ma8`H7j^4yn;)`OBCz}u(HZiN!0K~T4_z4 z$y#GwUC!*XImA#g+YCdT!h+orvdXZ;1R!|r3t>k7{@g;FReI52lH}%qeg;$H_0 zqF+60rj5)p{PcT$Ge`+gFTw3zPcOw6I<35UDX0rE&u07!3NwWE`&<`HI3y*7r@LHn zVH+U5#Vc}rwj6yVN4}~_|B^xM#jw;+e^TsuQ4*!B=CPYCWo_Db4m(J4*}46+5>`qN zvI9oRs{W%~$XYU}9dM&ADE0(xTs|{%Fr-QlRSx5MsUFA#nq_VEap5IHkqTGchjm3T zbH)n70pE(kik8MsZ|O@X9k|ixN35r|rBs2sL_03E-rkd>X1q41_C?FpH@8S^L`9CZKo2!8+hZ`a{JT@nLH78dBg zfq;^vfq?M-C!H?-Ukd+!3v?@ojaI~OsxN540;nM@4RQ8`XA%uU$-f7oN9iJl<#- z*y^1s;p*|WSG13_${{ibE_mZZd?0#YpVRo%(LS7-V^WQ_JKhR>^J>D|k zn_k;rFn)N59b;8pk!3zoB9(JwDT3Pbf-ymsfN2{8sBXWn2U9RqLK91Inm<_>>=@Ha`0jw=nl_eaj;_}MsF~=ZqtOI!*MKddQP7_$+9-) zJGxUJk%kIc#9e#c%S>G=N%hLHv})u5AmJk1so$gtr_65KUdA-=ZlhG@w+$~cm55YSt2TFfis~g`)XiEk= z)|?rjj-CanlrFCrH_#WwH+H23qlW{)J_g_NGylehB>>Zj1dAPJaAcoEh?=Fnwl74J z2bO@CQ4n`sv|2aZHLaO85}24Gov-249;@Nqbn@PlC%~QI2@v#wG`oZ4S+2Av{IC8_cJz6^8%2lExWtDggvCNaev!s#K#)e7y(i=V;wOl9Ou@$h>>a zo9E>(WwK>LKTbf4kUds~{p`VaEXC_zF%n;xX~eX#b8>g#f0Y;xHjV(3KqGF}y%0#& zc?-t;iTizC1%Mev7n0WuCxMHRd%R`sTCy|7e#*4=0Gxn64M6 z?h7M8au<;!8b&?kkEMgMT)4ZS-&U-jhv9|{sTcYcjaD@CVEad?hpZ6TXxw z3Ir4!radt8j{;aen=2pMglXObx<4gbZQZ|4`WB#}2g&o(i; zG@bQW^WWl{#vARm7wC|ri2ea?jC)?DC`<*ba+2#o>DYl9UKz$%@7y9_=CdUCr;X@(hu z^PuYc;V4;vSOMN@WB7t$f3fSFJ9D-S%c1L}h3JIx)t#$R=7&H~Aa`Iq*&7QuAj^|u z4RR0_PzocdoMTVk#lpCa63Mg@niY63UOC!G9J}|;*ndz$ICy(6|nx?fU}PQ_cOshZ;VPym-C_4 zWmSQFq7SzYf7c6soA(F;F5~-ivVaU+Ank8tRUUr|y_u>`btIh1=Ycg@nO9P&y<8qu z*wfI#yD7M2+TPsnk%?OtvOzrBSwB~X`cC96*h_l1T#K%#;@eF*yVDD3#5`uz+cM~# z>$cd)@EaCnsViLSCBif+u%@%-l#v}FZEQc+lV?- z##2U=Ao5(0Q03ZyB%LrNzG7xyZv#N92UQ$-9m54ZtnPVOwJYNqW}VV!OgQDx{OC1P z^Xaa$7*C0Y!?e$B5#)e*E#=>iky;IimH;p57UNYOVZEa@DWt2n&tdjfoJ)sx;iBx3 z@BxB{rgefeMrIlRUT*O!VKP{dzg-(j01KotIDhCuBWbFlDQgMUnN5E`$(rs;wy@X0 z^YARNrv8p!Z(4()7)T;P``|Cag8b5^p*z8fX0Ismrrdgg1G6y))!4@oWU?TN%wyuBc0zyWiFXCD%v>u+0G7KcXeOBg+9-i{6`dqDgol<9Om9DR zh3u5oV>d)q(}Pnk=f9~(QuG1PYv5EGK_b%)RfpDT*$r>CQKuHTwXnimi@J9hXG7;# zkt^|a5K{k2$(3&i4OaZiRSGA}503%nk)9EYBm*HRw0KPCB3Idad^>IELlAh_kwa2L zaG*qZb~3HVGjUVo zoM$CaR$vT-%9)vz7r0DUbM(g1sFTv=sMAV(1x$wp0|wP=g$Gph=dFig$G%OrIWQR* zE)ydgkq(Te@608m9XpV|*l!80aM-5N3lCwwXF6K5_%qi@%F3T2l-!_biN@C+uDr_) z*VAcs5w-avxfn1@YM>H*GAjt_cHTa76;aMBtx8+=aiqV#-c}ndVN3P32?hR@MO+Fn zQnzwYuE7WCtIb`@<=KGrt*ggIkR2j+lzgpv4ajm|JJ1J$$jnI7$b{;<#bgHpJ6i!D zRg;Kut&5d!Y?L(i7_CCRZLO8lrHx9?Y5lTvJg)H`s0t`}#= zYDjGs+&xW-86_k zvY^q2aUgns-CkQsFOx^rhD4OfyIyAN<^&W#Z*n9DV)g}V^q)94nq(hjEW9T*mh7g9Th8J!2vi ziwjD4k=L_}$KA@dFGy#dC$!-0bOKXEf@a(G3P2nS|8!+n)t#+-Ex6?=?cP-T7Otg? zD-o>9#@TU%C{M&PqcXM%HoucBl6SxGA|>s9{DV*WEsN@K4WET$Q9;ua1U%8xN*qHoZ`6P;I1&r7#W#kURV?7NKa#q@0dPRgi+H zxSkAdP<^*-2s?A;azqDZ#RNfIM$(LklgT3vaj$^2P;|RH%1S? z+6_1Lk7+EM5Evzdo2$IMYN}bKXR-ax+#)aG0GCQ@ehfAg%4J<%K+dA-h|++wF2@cg9I zfFOhQagWaEDLp+O5A82$#*33{oL3S493M65PEA8g>=`t}(3ERKir}YxvTB)ofz{!1 z{(iQ+v(lTw9oF#$)zXY7hjhGKvPYoh;&d}#vC)pTmf0dtRYTK0Xv)3&zmm-VXo_~{ z9VQbnAfV8HLE`_&fs(W_`Hz^WQnr%W5JmX5{0S!yx3&_roZrrpo|T=~6?bIwmv7xJ z6G}Fy(Fwe2a$YHvTl(>Cuoxl8lg$Fd^UcaiG0E{V?zGuaGW!)fq}xXsYMPk@s2}~9 z6S*;W^y0I`I$e=eKaA%~w8IofAefj9pDry~|><`w7=dc2+;( ztp00HD^_-3wHmC1k6K|EcHl$ZZZP<*i=hv+?@w2V1t!WmrQuSzi5NxH-8)Y$KbAHg z?l-X4CnE;7Z^}tpDtH8FYGPi&0RkiSuVksB%4kiN!E-f*e^|G@Wq*5~vWC$1s)~eh zLK}mLjuMcjfYEUTg&(Ole^}5H*^C3K5?G5?N2vv;ydQp^*S!5UioWlbVcPIuXOyh9JdoE^opNs>^a3m_ZkFbQI z@9A@RV{J02_Sf~VObE&d*M~PtXy?NXAaW^i@6UVi@8Ea z$s#Sdol3w(g`B8HV60WWL$ygecN@QYLbfIGCd2}7f;q~jSnqKb$pq@Rk6)m8kD3~L z&0K;R$vY{I3>{d-(~sn`usuvo>~H-6j@P+k#K`LE#a`P)rB=Zb>k@GiPi&lJYXU6e z2jdilOhQVZF~%|sugkEJ*^|@W=Ec9u4|9(N``fSG)uB)m?YW#VEi-dltZiPIwHt$p zGD22LZo7$%{(7B|h9isCK~1I3FqT8i#Ewbm=1&mwZ-JlkOV_s12103#ZvqQSZ_p_7 zQPIh2*#rLk7>D8K>ZJq(3eaNHXnb(co_Lkh8?N(h0H-W@I<2Mz)x@MP2q7~F0T1ts6Pghsjh>Ffk>3a8VcO6Sn z4}-Xwy?@0vo*zONMT)OJx26}aHc6wA%9bYi^*ILl^cMjD_bV+wLYs;+C3(CYIDY7g zidw$;U+e;_9vvr_U7H+W+j{K@v_~oSH5>*RE$Awcj{xPGIM{Mf)*LOjl<$(a!}W&| z2OGz$ugC_7TdZRokij~3a@Y;OYH$)i?mj57_i%R8u}vJ9=7P_6)>|B6ZWEb-5qZ1m zehx4VoL)!f?}eA|I@CzjiI%#Wxz!P#+nzSdNxkX7XB$Un%;H}W&7!H2UC9AG#wOX( z=I}e-JGZAhOUQ#AoC^kpZuGkxAe{^#XcrPH9O8K8Cz?;~rrPczyRG`fMAVy}U)HuP z)jz=hZFqQbi1Kl8&0ao30Rgf7b36V=@P?F`iT!_-^K7X}IBc*YaVzxXD^yU&*HMin ztg{Uokm8b-i6uRh4z6(-8ms+VNFYl9g8-_UE56@p!2;5W&op$-;b_AiFa5O)YRn|7|w6>Cba%GmdQ{J=ADy~mm zO0O_fiin)~oI6`bX)B?&xh8CcXe3iG{Bo%Vq#YQtw@gUHIhas?vSURVGqQG<_!JDw z)C`KVk!l`GUJR?a!3i}K@YNV)nc#<0oGgnOQ$Ge`2X2S7hwJMafv0UIejkW$+UqX^ z4T=`-*}fq;YS}q;jvx6SE!40ptV9^!h*O~`^w)WXkM2>HHFHcvJ?z*eV+Kw>*aw*k zcQi-W7E6k$B$Avh{s1t4CB=jHO)+ASR=q>ft`UwjF}m8>J$=8OX`N6QFT0*Tg;Z2< z%xt=&=k$F#p72*EDuywOCsJ<03wY#e<7eusrIaNxh{-#K$~l?m(|c<|vri=IZ;(Zc z^p(gVeE!-_d_z;zQs?25@O$P(`-Mz=xNNR5N<0xONJXG-7eGPgXrn)c92LeM3}K>e zXK3>V5uTx*RBCYhN9Z>Kxak#BBM3e00akZVg9FA+eP>a_@0b~$ATdY_e`&983(8=sgsRN zsYvV@QiLa}`5Hky_w;2$=Ly+6qrTIF?f{q7ZShnWn?P)oDopIH9lpx9KAdPy_Ri5= z!X?3}adhfvrsLG=f4C$VOkluve39>2xnCyaJlE5fDj{U)4w3C;2>uld>1uA;n%MY* za++4AQ%BESoq<{8GPjfF!yRbZepJNFs3j9i^gU47&xx7%&yM(r*6l3|G*q>I;dXm^ zNtwFbh0B>=-WRy?H`XZ_-(;f%%-jx&ucA|Dvd&)1{#y{Mlp4RpeyV>Q${4{-L(6p%g(Lh%^(6VR9z?6K8O24m}wQKU!pz zP))pim`s_BWyt^nu(h2+k-O1>m(fawfxd&70bw8>0-u=M{BtaosF@Ka5!qNbNVdNQ zCa^KP(ymS}4l-!ooHP6-gu(axT}<@~#=YEXNyb#%R1eigi6u4pRGR;~h&VQmi&4vo z)AVLl3wPqNsXM=eqQS?46C{%{Ya!#;Ah&Xl3o@))|4%0nI4 zS&4=ruy`hjE_nAOGiSVgFj();0GqlCimP6FW9^2=W$5t&BeQ&0WgLo=H5hXstY`l! zv{<#ddSJ8O{dRLI#xOl<2C=vcucBaoCuxPuft3}l=XWV(3O}Z9jU~V0;qW{=jmbIy z+Y*`-+_Y0{qJQ)m-%9eztnQNTEb5pT3e9yWN@?Q4sl+x=djrzawbWI?l5CIQKun;V zI0)DZrHR=ZYyfRlsXZ$G$oyTW0|qurRlp}AXBgm)fAVW#^%pAk*PY#WM!}zj{%zc4 zYM4d10@~OhF87Ei_2uB~Cdy&*XSd113$o0whn35Pf*G;Li(@j}8OU?NV4q9BRtVsh z`@2IH`E|0tX6K4>9hbBv8?g&3-k0d zL@PyhE~;Et_bW+`AkbNbsl!$-2VMqeq`ML#o<8^Qr;`0;CtR?|FMBehTLTj!{bm+! zc-nj##5V*G5%b_G^^bMNM}@R5Aus3T(z@i!WC^d4tYPb#l4UZokwE^<=oKqzItVTnq0Yv<3iH?wzlTdPOe>keQOX zImNsEx)AL6dRC;Fx5my&Lk8N%O><4tCqTP@^4D~9&*m+*;XJ2j_8#eiJ2_lfWO`O+ z@3x=ayTtOSzZPd);PM9`hJgyqy-k0sGW*7aZn{lHTj-zu@%A z1EDb|I!mFS<1TJ{W3m&MfG5w)h)-`{R+Q0r;#~a=<&M&5?+9@1);%AFm1Y$nuSuEJpg-B)sR)h{#MSV@#A{)fW`i1 ze1|e&15dW{=rjbQZS(8PX2qVSEy^Zsea6j&=rPb26>)5q8H`0vekArDQcsYyGC$|6 zL|RXf;AP2q>xJH4dIzgH_kKaqilY0?4q1ODF=JXWwSB-WO82P>I|z;|9AYlR5tZ&BNCwpywPq0vTBBNoomF^|n@DPQbt}tuG#u_eE*f znCfd9b?XTeTOU^Pg%JhU%_mI)8P+_H3|c8d=MjtT)Y>@jKi(MakbYTL!@bTdJjCr+ zU!RU%s1FWqxBmkx+IjqxcApRuI5@n~aTtHIL{&q<9GT#Czdd}vBhxr)%7PFLAvXnY zK#}&)FYEg^0zuGRK_tSn9tSb~0XPn-u;|RrV57aS}SEGce^kHh(XoivE#>Z0hcxYQ^`l_-gk(!e& zIw%gt;#WXQ-H99W?H7G6S4|3bEJBDzq~w_2Ai@}kqdI=xq=VhblASccWRkRs?v1Yy zVhjRkBSCQrpI^oOTR`h`HB1Zda+&d+VsXp(?touXiZsEP3L_0c7HGO@Q7#_+lqeT3 z%t@VcfV_L7hHy0@Qb_XP%%ycyuUGm2^#Iksx-w>9K}KcrQvAon-wLAlT?7x?ajVgT z{HIn19762~h^cmy2Hg4%j`?#mlSPAqF*kd{y8I$eaC+Ja4T??ubu{UA_mM(0xAu=@ zTT)g0&~-kXU7xPjke>2EHdjSul;O0JO^9LhnL^YRxF#Zk%N!jrv%N8AV`aMTy z7~X|2KAP%*J50G~?w8ke6xNt1<}Mi7PMs2;kR9{&w!Cd93;fdl?+R|*GY78aYx?3x zjiF`FN*E>KE!U#=A-9`ZLPTx}Y2)fhEU|bXuCY#(N74q7kmFNWa5>zXm@TrN7%&Q4 z`+U?C?5cQ_)C-1o`!O1}Nnj%d%#nAh5Oq$z;o>m;tj@?#5VLyF<9Sl8M_v%+P`5kw zG&d!ssK>q$_aM36D#CF1K@1-_MWUrt#xKXRhzS?)IoPPlfvP1X#evBnkDTVn*=HB2 z^bGJ$6lV==9tI^qv=b()50`SoL>g|A;?6fvmAn2!`z{)xQ>Y>*lpr`y(446!Vx~aF z3$=&yJM^>AOLUFzpj2i)kDM{aNpw@l5cIytti2Kr7gwi6vIEE?X&iKl3m@~8WGK2$ zNqP~A*2w0(_`Yu=h8ytg*PuRFo+BjE=nJUo5K>z&f4L{nzbRL(TQpj2S6pgqj@fU(d4{R&j+@D1z3%ZQ-u+K-|Ap+)~3M5eJ5q+suY0X+xL;F3#S zId<9TB~TY}*vS3}5|Vp`xwL2lY~e)OnMDt~(*a=TCeiRwKBtTRa1oWrh=mt4}deG!T6Fjrm=E*sT~ zVl=UgCVv}G;>U;Xti=g1mW63pp_!>SaSgF*I~z6`2MJ8fKDbu8k`D4|6}BYiQl>XJ zdBoORiq2&f*?a)2eLr`wD7 zNIhyT*YmdK>TRYKom_rvRo1|qc6dJ+WZ@(qBp0fZ@|#iqq<7y@JfIN3B8O7A5 zwn+E|BnQ!Zc!H*srb+cc?rP+v7(&7Xp=mz!A*_?@i*UHYUgTb!8E)Dder&^u0cB}E zbF^Zw^cP2LvBP0A5l$V6Tgf-vz@PF}O0t;d5p(qlO+cQ)%3Kf$F8m8bDvZvr(}lOVJ?OFWF?lgZQLW z)z@tVwyRt0%6v|j9hq@z`|9w~_aIRdVk$}rCm|h_rFn^?Q*`}0J zj%W7QXbnx#cq7ThR3b2}o?#M~@08|B8bPlmV{40PMzIF$-$X|H=PT!k$Ybq_LZE6u zVXCD#>OJLM_VUde)%y93eHD>d>Vt&KTd!-Jl~hs}7ATinN*nL@SrT z&qp-Rtt0E{QUUbQrS{4gg{ip)7JfuGCi?ET8am#~iv{1U>LZ%25G#`V)ly$uC9u+H z9dpoc+)!-`T=X7N3m5^hE(_Ik6nV8?r24<$=d|^Hd{F8v%Vv+$9?BWd9@<6LMK(iZ zW&MpL%@HbcR8&XC))r@f-_#0r@}QP((M9DA{Ea`Ewe3f^YO39(UeaxqKL*X8WRpp* zsJ!g9$_1smr8{V^N*bT0`D!kos^x<7KlqR0itRKr=DW+?8c(ly<~f$-jkpLZpqGxI z=P!KjhlbU)UdxOInkQbjkloq6(3g(>s6V%JK76u$T5KNGvUrqrcX1UN!co{?a5G~1 z{LT5Jjl<1&lEwXz5o!=Rk4@^`L2s*hvg=j;hUh7&q8Wjz0>BKRqW93qPE&$a1)V@b z4!bJg?5onLG&LjAyX?RDTQD;iRpnqAxmkLuPr>%Q75mcCbMbS*Bl3eADg3cx)#HDq z{X6_3*Gp}+;snUo!wUPk({A_9|_mnUuw3$fS8+^5AJtWR`{auKJgdNFe@yZoOpn>>Z5k{}YldsanY#2>+ju#5{w9SM) zDV+J4WNqJdYs(2_|9*$#1BoN}R{h#hh_J7rfw5zT^Pw^&XD6`%$yW+L&<4K%S$US~ zw>KL*UN(+aCwxBSDXN0rt)IX!m=x-$Vy!%|m;wcHEa!?wo;ASc)mM}3DPg_6+8jFLk(w)VYNibRf+S<7b=b^mKG)&E&r56^cZDxu zWEf`P8;22c`~jlmogy2JFShJARUYyERWMNrvM?eIZWS}s^ePkN^%nyM&d-o5~Y2`ja%Bn1LSy)bDU||B@i`~ zyo=uRLm%l#%$ZVDU@Z9zClXUBT%vvk(k&fhSXO`w`G@2_7SVyZ* zyTRoLLI{hiM(?StXD)**6gWCH&xt&$<62LP41UH)eEv@$2^9iVmV`TOfWRr0sP@c~ zT^e?pR-myU{90Wzh9%N3o-|0O-fF0joMk1sDU>d-&)l{`8K_{0b3h4=rs-bzHEhTI zifyHzd2D^zH7d&t8D@>5TG=)M`JE6c*4jvImf6xgfaU(peK(V0U^r7+QD4Vl*%QJ6 zZ zSSE%UnnaGzyy!ndElBIsp%P}cAL!?R829C2z~eT_y0qjL zv2BDsM+nKlmwX37UAmUVTD8;1o-A5P2*@8rDyq9)xD{P13#gDG?b|u!YYE#QmMmm8 zY0SPQtdAS{eN_$eX2h) zhAeXdC7a&``#}4G+7g8u!(5G5|2O0OKT%8jyT_92zZ*~k2_PVx|7o{W*51b0%<_N# zb61)_F6*pFKWuN5ip&}U8NBr!TQ0DEG{n*qR?y_J*H;!FpOMtP8U`PhY~(8`KVQZ~ zYiPP;vh5icR^Irk$;QGDM~r{fjxW{d;2`aS3q^4eGT?Ax)`hOz3QBaC-f5fU!)9aP zD9x>MR;5L$g$XGgL4+kI^5q02SDtLjs*=h-l0;&j$NtVgTCHQc!4>Rr?@`0XyaGRo z9**P*h5Z4mHb|Si(yISzcO|J21~FQDJBAlVU}qlm+c zj``t>-rX4+Bbd`#38R_nBQSGQPKyCeD?LyK z)o~lbC`a7!l3@>V2uB)xAF(j=R}Tw4Co@8#C4!cB>+5@T%3=#}zOGJIBQ%4!>wk+a zFcpYWbn-Y8>g$2#WwQZ=jV{JO3B-hgtYpRmKULlh{^r4s_Zb0X;vy|Hgv|`|jxnc& zDPr6D&lVFzV=1uUx4>Zqd_mknS^|*%f*ea`{@AXNNnBgy%qh(4?s6fEgX{py*kQCi z8LWU08y@Q@JTi(2{<#YYoP&a#A=?wrj*H=7s@o5J zd)TLX=_bP^dZEeUGYy7|3LF4Vh{KaUNnd$bR?04D-wbsJ0Jg+?sUe}IGHdE-C08u} zlsWNS-Q4hrfbU6K+3TjV6d&XpMM0+X#)mG3{s}&AZ0$+;HY-c}dnIdyC&#=&mxr8M zgD8?4xyIp#H}w=HFcPW?i8Rx!(LKVy^UDr)1na$lWp08urXi}7$UstxZhtdN^mK(+ zM{}3KQ8;~Gv3#05#G|qAa}M&+;En!OC+hRouv()b2$myUh6o29NNAMqxs@*zxRPsD z!Ln}OFP6PYuB@@=1*+KA_u5<0rdjlg0Jy++pU@bj7DYno=~-^;NeYWw$_6DMELekXTWh+5K&64YYD9>w@aiu(~h5AM@1;K14&H`YG@;(YsO(P+J#KN$bW4-^52~? z_tVDjq+H}fM00fmdC9{GJ4Z%Bh|!r+1xwwGbae-8M#)(5EpKyK)g(#b3JV?-5A_gg-;av>123FjyIjWkaVP%lN`rnpvGV zg|+^{LMzn0g3>YAOvgP4Du45XRv*nS91VQY?Sz4XkBp2y8=(sQ1N;kh+wG>4U&)MW zCDa+*Qxj`KZKN8NYD9Ftb^quWQeByZMG&w{=|aNpU&%Qq%loZ`g9CHjb&Sap9)X9k zx_7ytJ=y5&Z(rCE!Osdf$%_Fpmt_bbpjdnl<3|JB)3CblzdsA zQ`r1m3ht)*eYk%`HYEq-Lg5S?Rf@}tbtb5NhB$t$(ldcRkZFw?BgO{{2?qx^P3(Ad zpkVPo^SS6zM9sRe79v7q%aO7EDZF3AzCw(>W=(&qz;cN0boP47HBG20bLs@;)b;a8 zb&&~n6Ao@F)_95y+5GE=W9 zymNEx`EE;l8w*jdpHC$1l=qxVPgKt;<6YgfFa&|Pl?; zVz()aEktpJE-L=@JwQs94ZW?c&)CJhb-q+JfI|Rf%tw?NQpOIB4c;Q}Pa|EW*Kv}o zeEaIdvz=(AA0QhzM{-#=me|gsPA6PbS7eV3frr}kWun&M!u*a!K0!CJpB&&*6$g{Vzk=jidr=b$z3QawTh{yub!JVxH_L7g6 znv;>XV|w(GF2ue~D8KiNQ5FjhRI2J`^~NnoylzO)fT8A1Q2OPw>arul}igD6Dy%tBbPdiR1N0>fm1eX0PR<;z3vk z9c)PV^Sl18c*(m@gObyA^=_JMMmA=bZL>Xl-pIAmJE3udy zf`!o}Hy`r`i=l!=i%KUM6EXN%-sSw}y;r}Zf|jHe3S*7LXBVUvA29cO&Hfc}0^bDU z%MoVYY%|nqrwwkntQD@4BctJbmz5k4ia-;rjP^ijanmTD)=(yFM6ON!q3ltTS9#ND za+7;vX0J5lmW(6HMQ~lSd`zRac+w|P-ThXH*vA_46p}YQSi5l53cPO3eOc-6T$WO} zMdvovJ`75iU3}d0V=!S%;@+GUCf#z-9A}iE7jE=Iv`$M7=-zTCBxjJrE73=o8^=D3 z*Jwx@Mhk-W)noLI*eVzM4zM^6EWtKFNC=-&V;u~UQ=ND(Dn)(B%qJaOMigDj9< z!&!A21k0<{{)(|Zzz}zv@Nb10-&c&$XBln#vuw=vZT<0OrOp2BdxAikOJ+9iVw2y( z`u#=lCPrkA4H2lTs=kl$YFQCl6(VT!61B3D)x9mzVd7u(w^db@3d#-14{7}TKEs70 zu+>j^2a7;f7sg$6-kz*@7&QUEZ+*hvK49Z0`3yG=Kivg-qMo-pTc%t0F0x$1r%9Tj zWqpj0YfJGXKmXl&E&j`*dJR4j-90DsAmOAc7TE}FK>2kD7> zlv>R+Y(+oli*G+=Dp{Zp+T=@hiAz+E_IF+OVG3CMNi6vp2YsJkQ4R2traVY9?^0D^r@ zPSKl?9G1lU`5<|}Kn?kNeM976Q*Q+)@DO`QX@obM`|XZ9usG3R;WRVj^qAoN4_=DC z)zNV-uJAy?dn|(m6<)SLuadGO5(IpNx$1Ug>V z)DyxR90)&g3n6B9sw(x@(;WWMDgbj)%{rwDNdV)q0J*L-75jK(3ResbJ_H5+^%sWz zw>KhmJ4D7I6Wh|$UrXznG>4$J_`bwB(ZHx?A?6L$XeRke*=hddE)xQ3?R5NTQbp)x znSp1dEZ@${mm0$wT2`o{?%cY7P~|bN2&au&&TodLvz|oHbOuf@Uu) zx>i`U&%RQ!9Ij*!L=8GGAK#&K4v_>e4;uQuZ&cbT3|kg%030c+V2ABJSY6&KxPtOW zvl~;>ZR_8(2l)%X!e*WvK8wQ?;`yu8?vY}U6C56bb>EepJ#_jRxnZjA6KBr1@{ZtP zQ!WoUwdxEM$t1Qb@Gz{q{ys@%9wpHtQO`KsI~ihZ9DqI@kx_r(EJ>{}#ivpy-)GOz z@L9~CAsu-YeL(Gg+Ffz+*--P@STQ;On9XiQ4P8vZ*fgB1EIII?BMfhQ5@cN-*_BLs z;}JheQ*RwPl>Nzu^JJcud$eVh>`NY~@C5h9Pc$3_%5|RhAjCgOif~E{UuSxwv;A^)4t_}S^5-U%*nbP2Udt5X&R-Bm~UcR^83Z(W{*Qmts2M0 zq33dj>^`=hf4=yPjgNq;CcwGMbgk31(Vvn1ejX)T21W`_G412!a52Zk+l86?9kZ*Y7<2jQZlM~rvbSp8vlDz&>!P*vi(zya- zqQ5iJq={lw^K$I2)W7cgo#6?GrGN4n{tsy$FHAgiUX1b(blJtsQ^&_(C=(O?9f8yP zlg;_3jzx{6yyebukmlY{a;GodO}noVhFpaf4jwsGt8{Hdtd6siQd|1CN%SobmtA|* zsJLf}mc>gHlp>Cl_r1q0Y{FP(SY(kC`HzZbfDZh}*MNZYZPND{mYbJsrG8CAYkBj1 zYk5iWO;u{L9l2}KDy9TC?RZ9ZvC0>4+~#n0Y>oTyfVhmls^_YV?c3$k(BS2XL(fh} zxI}Y^0V$`Zz^*@-X$X`}4sz`tRzsiA(Fk|a+~A}~panvb+Mbs4FZqL0;h z4c4ne`xaZ$Q0xG8@Yg5I;JzmGt~UFyUC7sVdA9$WUIV+#XuULv^K{=f1hUY3u)cf6YW{{J7?wb5tVN#$ zIoMSUJKROV?ziV{E|m)sCTUr( zK)Ea~1;))x`pjV(B_4`H&8IW5Mhk8T#fC`XHXn}Dz}>yELM(x9uSa>yq;?I)R6wIyi( zmU?j(0~m_w*b24soknmq7TptDEeY4>JIn=8DYlXx8l9dfi9wGLS|NxDUXGUn?~Zci z9yu8RK^jPFT0FB(+C!=jzbOK8O8_k?5G z)gHHSzVQ0V>QPLp6_AcSdv$&;9V+xnlTCcoo4`awmqjBtOK40l&qlZ(p0A7V2HTt) z-YcUX5zO&A+=P4R%mZn?sA0?y%<3V^3LRd*u#ld{77coZr&K!`FZ z69PQ@K`<{eB5(TnO{Ek>4VV$UqWe@3run|wMAe9He&d>vh6vYaMa7^~?i2J-^8x}% zLK7e&7Q8ov#o2^A30Q1ZQkuB(<;)taPM??wNr%=}MNY^oj#*QncVp^$=wyPTbj4Q$ zZelO{F5_xqcvr=Ibc0^5xt$%Hj@7vGa&p( zeapH0crWipdWxm@xP(xJ-ImHf6)Ib6J|p$avH4GMF7YlLx7we=rQNA3Bf==K-r9~e zxNQF^BRX6*;G)HuY(V+ih3KkAGHh$S=UQ*Yxfa3WDtYGEm3ql(^$s<1M|q#TO9gSdTo(5nM6%sXJkzW{zpsAMn~yoQ&d zz>^XzwcNkOy|{{yb7lV$*S+@#q~|)o9fgg3*&n*a=^2#YCNcJrtI&v%FM4T!By~7^ ziOL~hoDu7Kegv+N(k_N~2)+h{3g>PxL-;x|O2|{3SzzbHOSn&sT>$pBc?nL)#e6aG?4(Wn3DvXeO>j zphI*G>vH%!E}@HBtmjyWVU}Uf#vBOITx67b>Qt+?TK59+)$2%QV?*FVMZ?!+&*iHk ze$m9Neh3soT)t2D)#+lY`SCJvGAnE|y{h>L8@ZZ=Cz^G;=)>1#TuxCeekP^X$~~^8 z^fp<`5aemgmaxTJfvdHh_Qf-D{|dxUrB0cAmG}TZN*N)t&q$&9f;a0l@!NBYo*WcV zETwX#HReCO;2gJag2TkmB?RcA?_Jd?=}-tc)X8qpBRh>RJw1!Yk00N6S-B~zHU0^h zEt-kG3o2xZ6i8Z5xhzH~oq)>zO_+^ZM8qWBjmKYNc+@_dz%?l6ygW?0(jH2G@Aop$ z{#U)9Ig7Slho^vq2iliXcO(n+Fx|B4t z&oPiy^qFyi5&MrKKm8Ce)YOY4Ixr8r)O??dc)Jn31s**gU%;1G*}k#@%X(9C_YYvh zW|)goxC$jLgpQ?>AWqL7nsw(t1vzi)@UmyT6nOFoLr^RWhpj+{D88^Vg+&KqTPHS3 z2M$F!XBpu*SP5!R$43Zz<->@l^+)n*i6G%jR&WdM`EvjW{_XAexU3-IDi);zGeM45 zeDLqCt8?Vm@fr<0h-Vbzv{mh2C-4;b<(5W#Jl};LO|AJjeMT;G1bIcP+ZDp99GJ!U z5i^-Z@BvY&JrvF*uqhbLBG+Lxe8)*VuDF0W|1w-xFkVWkvyS*~sw8D)B%lVZ6SK*>nT(aTwZxE0S&?TMHVRZFhdhOn)$wzBUNqY;fp505 zqcI;@dC~JI*nCf3TNhcG3S))SL%hNk&AbZsZ+1q!chJ5!hfWg|o2J>3y))lx7{{YQ z98pPH{g)!_UDtbYWDMM+DA*9gsuCpny#*0{Tt{bujtmUpfg%OHe(Ewwp=)OI7zR*x zi;cox(Rqv9N%yc4Z{d^l?i`iWhP8LhN{X89s9E3R>hY$mKBeZ1V76qNeu-cZ0<}t# zGIMkS=$MQJWp7WP3S$Se)AO$S|r3(Usml3_xU(0`X)k8epz zVyVjqCqohs%U}F12iMCqy-C|-YLgN-rZO<+n5?T$c1*YXnK%0e_x{qQAkGKbssY&4 z^|x4652&#Uo+)Blj+zn{Ov>QPlu=3`(N!@<(wodW{;aQ9-rQX;Y_zo8p6_Q0?CFW-7IR5z z6Mg;xs$k^DR=cz8TqZXX@kdUN068bniMs_kB1M`?s(wKekI}IDrM3WzoGoN|h1Fwi zc#SsKqJ0rRxJr6w+t(6h7-kA%Y>zO$dAW1ZI#*l#y51JRIVd)#n0_HGfqGN3`3{X6 zc%MuV?|2zbli5f|Ribz$BUOkCXI0w%QN%Oq(55t0>p-cBsAtK1JU@kg9NXk@C@XFw zF$3)K2O{Uxo5|+l?e~?kJ>U_c`lZ0017=)vl3qpOvHKz;5JwcA=3Yf zPEONvoG2^Yqpbjq_Niq>6#U*g%lmk%X13J<2<9YbdB@%9Ner_5zVml1<@?R1w&A#u zV^v9~jiLE%+{!Pyf0|v1s1i5@HdsNEf%8l+Q@MEcuRWpn$meO z$Tf8}Rx1md=4ngnN#2f~5pY}dy%fDXBuzvzVbCh75y@ZV?DlAouvn%4(LR3{XTO@;Z1-MyR=zTxt2!o?4A^ zz0vZuVSieN?RrZxWXoPda053r2bG*CxmQewSxJywRh}X`g7KriT#)tDStWEmbssX} zvr1#T{i4!+oo5v)aLe$=Z6#VHv67}M2SZH5_D_AvYa!GHjhno(pm$+6UPSZ+&f^d~ zqSh6f6HsxtthZw<~d^|>M8p_NpsyS;%lT16^wSB-9uEve!_27z4!4Y@3 zy*(myGDx>ji>TV(0dqSX%2evSCuSkedfEu{AQ69>u8zWimpCb22k&*vX&0%Gb+LHk zzjBv_`mLnqf8Qfa)^4A9%R-b6b6LzS24g>il(OXsjynNc#pMMwMxpw4I;QGs|C|z_ zdaPGK!*H)Q&`f~e0&oN(Ils2CeT)QyzZi6?TNUb_0lRcZ+|&@6oOZTbGItbZJyyj7h4(mBU2}VN>Iqf5 z91NEj1AEkNG4sYlk+{C1(@2`?!IBsUXq*Q{xMNlOUU#)!ErLQGSNnwB^DA$YNP70s z=y#c^wC|MbJng8ZyY`1m;DyC!YF4}N!;3uT0^}3pDEJ|^@$f(dmpkDY+r&IN+EnE! zrF~I9Zp?|t>6kD%79n6l980vT7abF$k+3)eHS0Y2L7+nXL)DG#0q0hDzx{6%d3;H5 zyx#u4rC0ghFfSer2Z{06ZLHdbrrW6%;1qBRC921|!u0v;1Hp2)D!rrEcCU+~iaz|w zf9wj*6G#Cy7%HakE~2=Fu*Nn8be}Rhf)Vd~l|hX8?zxVV#Ihk4-A3lAav1UTHR9Mc zjfSYD8USggY4r|6zj^TRSM%eaIY=Ku~XIYYbNle`E+$OGf z2?-se^VNNHZ`BF17TzJa)1 zni{1766pA=J)BaIwMgF0So*0z3HS-_17ol2{s$+aX13={^_t9`jtlq{aBj+NV~zM$im#%nbcf{kkV9&5KH2dWVwY6GX{@(gB2*HFvTv4fAi$ zOC#cYkuHnZs=gms5GQ*

    ', + 'heading_row_start' => '', + 'heading_previous_cell' => '', + 'heading_title_cell' => '', + 'heading_next_cell' => '', + 'heading_row_end' => '', + 'week_row_start' => '', + 'week_day_cell' => '', + 'week_row_end' => '', + 'cal_row_start' => '', + 'cal_cell_start' => '', + 'cal_cell_end_today' => '', + 'cal_row_end' => '', + 'table_close' => '
    <<{heading}>>
    {week_day}
    ', + 'cal_cell_start_today' => '', + 'cal_cell_content' => '{day}', + 'cal_cell_content_today' => '{day}', + 'cal_cell_no_content' => '{day}', + 'cal_cell_no_content_today' => '{day}', + 'cal_cell_blank' => ' ', + 'cal_cell_end' => '
    ' + ); + } + + // -------------------------------------------------------------------- + + /** + * Parse Template + * + * Harvests the data within the template {pseudo-variables} + * used to display the calendar + * + * @access public + * @return void + */ + function parse_template() + { + $this->temp = $this->default_template(); + + if ($this->template == '') + { + return; + } + + $today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today'); + + foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today') as $val) + { + if (preg_match("/\{".$val."\}(.*?)\{\/".$val."\}/si", $this->template, $match)) + { + $this->temp[$val] = $match['1']; + } + else + { + if (in_array($val, $today, TRUE)) + { + $this->temp[$val] = $this->temp[str_replace('_today', '', $val)]; + } + } + } + } + +} + +// END CI_Calendar class + +/* End of file Calendar.php */ +/* Location: ./system/libraries/Calendar.php */ \ No newline at end of file diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php new file mode 100644 index 0000000..da47b5a --- /dev/null +++ b/system/libraries/Cart.php @@ -0,0 +1,552 @@ +CI =& get_instance(); + + // Are any config settings being passed manually? If so, set them + $config = array(); + if (count($params) > 0) + { + foreach ($params as $key => $val) + { + $config[$key] = $val; + } + } + + // Load the Sessions class + $this->CI->load->library('session', $config); + + // Grab the shopping cart array from the session table, if it exists + if ($this->CI->session->userdata('cart_contents') !== FALSE) + { + $this->_cart_contents = $this->CI->session->userdata('cart_contents'); + } + else + { + // No cart exists so we'll set some base values + $this->_cart_contents['cart_total'] = 0; + $this->_cart_contents['total_items'] = 0; + } + + log_message('debug', "Cart Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Insert items into the cart and save it to the session table + * + * @access public + * @param array + * @return bool + */ + function insert($items = array()) + { + // Was any cart data passed? No? Bah... + if ( ! is_array($items) OR count($items) == 0) + { + log_message('error', 'The insert method must be passed an array containing data.'); + return FALSE; + } + + // You can either insert a single product using a one-dimensional array, + // or multiple products using a multi-dimensional one. The way we + // determine the array type is by looking for a required array key named "id" + // at the top level. If it's not found, we will assume it's a multi-dimensional array. + + $save_cart = FALSE; + if (isset($items['id'])) + { + if (($rowid = $this->_insert($items))) + { + $save_cart = TRUE; + } + } + else + { + foreach ($items as $val) + { + if (is_array($val) AND isset($val['id'])) + { + if ($this->_insert($val)) + { + $save_cart = TRUE; + } + } + } + } + + // Save the cart data if the insert was successful + if ($save_cart == TRUE) + { + $this->_save_cart(); + return isset($rowid) ? $rowid : TRUE; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Insert + * + * @access private + * @param array + * @return bool + */ + function _insert($items = array()) + { + // Was any cart data passed? No? Bah... + if ( ! is_array($items) OR count($items) == 0) + { + log_message('error', 'The insert method must be passed an array containing data.'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Does the $items array contain an id, quantity, price, and name? These are required + if ( ! isset($items['id']) OR ! isset($items['qty']) OR ! isset($items['price']) OR ! isset($items['name'])) + { + log_message('error', 'The cart array must contain a product ID, quantity, price, and name.'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Prep the quantity. It can only be a number. Duh... + $items['qty'] = trim(preg_replace('/([^0-9])/i', '', $items['qty'])); + // Trim any leading zeros + $items['qty'] = trim(preg_replace('/(^[0]+)/i', '', $items['qty'])); + + // If the quantity is zero or blank there's nothing for us to do + if ( ! is_numeric($items['qty']) OR $items['qty'] == 0) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + // Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods + // Not totally sure we should impose this rule, but it seems prudent to standardize IDs. + // Note: These can be user-specified by setting the $this->product_id_rules variable. + if ( ! preg_match("/^[".$this->product_id_rules."]+$/i", $items['id'])) + { + log_message('error', 'Invalid product ID. The product ID can only contain alpha-numeric characters, dashes, and underscores'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods. + // Note: These can be user-specified by setting the $this->product_name_rules variable. + if ( ! preg_match("/^[".$this->product_name_rules."]+$/i", $items['name'])) + { + log_message('error', 'An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Prep the price. Remove anything that isn't a number or decimal point. + $items['price'] = trim(preg_replace('/([^0-9\.])/i', '', $items['price'])); + // Trim any leading zeros + $items['price'] = trim(preg_replace('/(^[0]+)/i', '', $items['price'])); + + // Is the price a valid number? + if ( ! is_numeric($items['price'])) + { + log_message('error', 'An invalid price was submitted for product ID: '.$items['id']); + return FALSE; + } + + // -------------------------------------------------------------------- + + // We now need to create a unique identifier for the item being inserted into the cart. + // Every time something is added to the cart it is stored in the master cart array. + // Each row in the cart array, however, must have a unique index that identifies not only + // a particular product, but makes it possible to store identical products with different options. + // For example, what if someone buys two identical t-shirts (same product ID), but in + // different sizes? The product ID (and other attributes, like the name) will be identical for + // both sizes because it's the same shirt. The only difference will be the size. + // Internally, we need to treat identical submissions, but with different options, as a unique product. + // Our solution is to convert the options array to a string and MD5 it along with the product ID. + // This becomes the unique "row ID" + if (isset($items['options']) AND count($items['options']) > 0) + { + $rowid = md5($items['id'].implode('', $items['options'])); + } + else + { + // No options were submitted so we simply MD5 the product ID. + // Technically, we don't need to MD5 the ID in this case, but it makes + // sense to standardize the format of array indexes for both conditions + $rowid = md5($items['id']); + } + + // -------------------------------------------------------------------- + + // Now that we have our unique "row ID", we'll add our cart items to the master array + + // let's unset this first, just to make sure our index contains only the data from this submission + unset($this->_cart_contents[$rowid]); + + // Create a new index with our new row ID + $this->_cart_contents[$rowid]['rowid'] = $rowid; + + // And add the new items to the cart array + foreach ($items as $key => $val) + { + $this->_cart_contents[$rowid][$key] = $val; + } + + // Woot! + return $rowid; + } + + // -------------------------------------------------------------------- + + /** + * Update the cart + * + * This function permits the quantity of a given item to be changed. + * Typically it is called from the "view cart" page if a user makes + * changes to the quantity before checkout. That array must contain the + * product ID and quantity for each item. + * + * @access public + * @param array + * @param string + * @return bool + */ + function update($items = array()) + { + // Was any cart data passed? + if ( ! is_array($items) OR count($items) == 0) + { + return FALSE; + } + + // You can either update a single product using a one-dimensional array, + // or multiple products using a multi-dimensional one. The way we + // determine the array type is by looking for a required array key named "id". + // If it's not found we assume it's a multi-dimensional array + $save_cart = FALSE; + if (isset($items['rowid']) AND isset($items['qty'])) + { + if ($this->_update($items) == TRUE) + { + $save_cart = TRUE; + } + } + else + { + foreach ($items as $val) + { + if (is_array($val) AND isset($val['rowid']) AND isset($val['qty'])) + { + if ($this->_update($val) == TRUE) + { + $save_cart = TRUE; + } + } + } + } + + // Save the cart data if the insert was successful + if ($save_cart == TRUE) + { + $this->_save_cart(); + return TRUE; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Update the cart + * + * This function permits the quantity of a given item to be changed. + * Typically it is called from the "view cart" page if a user makes + * changes to the quantity before checkout. That array must contain the + * product ID and quantity for each item. + * + * @access private + * @param array + * @return bool + */ + function _update($items = array()) + { + // Without these array indexes there is nothing we can do + if ( ! isset($items['qty']) OR ! isset($items['rowid']) OR ! isset($this->_cart_contents[$items['rowid']])) + { + return FALSE; + } + + // Prep the quantity + $items['qty'] = preg_replace('/([^0-9])/i', '', $items['qty']); + + // Is the quantity a number? + if ( ! is_numeric($items['qty'])) + { + return FALSE; + } + + // Is the new quantity different than what is already saved in the cart? + // If it's the same there's nothing to do + if ($this->_cart_contents[$items['rowid']]['qty'] == $items['qty']) + { + return FALSE; + } + + // Is the quantity zero? If so we will remove the item from the cart. + // If the quantity is greater than zero we are updating + if ($items['qty'] == 0) + { + unset($this->_cart_contents[$items['rowid']]); + } + else + { + $this->_cart_contents[$items['rowid']]['qty'] = $items['qty']; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Save the cart array to the session DB + * + * @access private + * @return bool + */ + function _save_cart() + { + // Unset these so our total can be calculated correctly below + unset($this->_cart_contents['total_items']); + unset($this->_cart_contents['cart_total']); + + // Lets add up the individual prices and set the cart sub-total + $total = 0; + $items = 0; + foreach ($this->_cart_contents as $key => $val) + { + // We make sure the array contains the proper indexes + if ( ! is_array($val) OR ! isset($val['price']) OR ! isset($val['qty'])) + { + continue; + } + + $total += ($val['price'] * $val['qty']); + $items += $val['qty']; + + // Set the subtotal + $this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']); + } + + // Set the cart total and total items. + $this->_cart_contents['total_items'] = $items; + $this->_cart_contents['cart_total'] = $total; + + // Is our cart empty? If so we delete it from the session + if (count($this->_cart_contents) <= 2) + { + $this->CI->session->unset_userdata('cart_contents'); + + // Nothing more to do... coffee time! + return FALSE; + } + + // If we made it this far it means that our cart has data. + // Let's pass it to the Session class so it can be stored + $this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents)); + + // Woot! + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Cart Total + * + * @access public + * @return integer + */ + function total() + { + return $this->_cart_contents['cart_total']; + } + + // -------------------------------------------------------------------- + + /** + * Total Items + * + * Returns the total item count + * + * @access public + * @return integer + */ + function total_items() + { + return $this->_cart_contents['total_items']; + } + + // -------------------------------------------------------------------- + + /** + * Cart Contents + * + * Returns the entire cart array + * + * @access public + * @return array + */ + function contents() + { + $cart = $this->_cart_contents; + + // Remove these so they don't create a problem when showing the cart table + unset($cart['total_items']); + unset($cart['cart_total']); + + return $cart; + } + + // -------------------------------------------------------------------- + + /** + * Has options + * + * Returns TRUE if the rowid passed to this function correlates to an item + * that has options associated with it. + * + * @access public + * @return array + */ + function has_options($rowid = '') + { + if ( ! isset($this->_cart_contents[$rowid]['options']) OR count($this->_cart_contents[$rowid]['options']) === 0) + { + return FALSE; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Product options + * + * Returns the an array of options, for a particular product row ID + * + * @access public + * @return array + */ + function product_options($rowid = '') + { + if ( ! isset($this->_cart_contents[$rowid]['options'])) + { + return array(); + } + + return $this->_cart_contents[$rowid]['options']; + } + + // -------------------------------------------------------------------- + + /** + * Format Number + * + * Returns the supplied number with commas and a decimal point. + * + * @access public + * @return integer + */ + function format_number($n = '') + { + if ($n == '') + { + return ''; + } + + // Remove anything that isn't a number or decimal point. + $n = trim(preg_replace('/([^0-9\.])/i', '', $n)); + + return number_format($n, 2, '.', ','); + } + + // -------------------------------------------------------------------- + + /** + * Destroy the cart + * + * Empties the cart and kills the session + * + * @access public + * @return null + */ + function destroy() + { + unset($this->_cart_contents); + + $this->_cart_contents['cart_total'] = 0; + $this->_cart_contents['total_items'] = 0; + + $this->CI->session->unset_userdata('cart_contents'); + } + + +} +// END Cart Class + +/* End of file Cart.php */ +/* Location: ./system/libraries/Cart.php */ \ No newline at end of file diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php new file mode 100644 index 0000000..4912c4a --- /dev/null +++ b/system/libraries/Driver.php @@ -0,0 +1,229 @@ +lib_name)) + { + $this->lib_name = get_class($this); + } + + // The class will be prefixed with the parent lib + $child_class = $this->lib_name.'_'.$child; + + // Remove the CI_ prefix and lowercase + $lib_name = ucfirst(strtolower(str_replace('CI_', '', $this->lib_name))); + $driver_name = strtolower(str_replace('CI_', '', $child_class)); + + if (in_array($driver_name, array_map('strtolower', $this->valid_drivers))) + { + // check and see if the driver is in a separate file + if ( ! class_exists($child_class)) + { + // check application path first + foreach (get_instance()->load->get_package_paths(TRUE) as $path) + { + // loves me some nesting! + foreach (array(ucfirst($driver_name), $driver_name) as $class) + { + $filepath = $path.'libraries/'.$lib_name.'/drivers/'.$class.'.php'; + + if (file_exists($filepath)) + { + include_once $filepath; + break; + } + } + } + + // it's a valid driver, but the file simply can't be found + if ( ! class_exists($child_class)) + { + log_message('error', "Unable to load the requested driver: ".$child_class); + show_error("Unable to load the requested driver: ".$child_class); + } + } + + $obj = new $child_class; + $obj->decorate($this); + $this->$child = $obj; + return $this->$child; + } + + // The requested driver isn't valid! + log_message('error', "Invalid driver requested: ".$child_class); + show_error("Invalid driver requested: ".$child_class); + } + + // -------------------------------------------------------------------- + +} +// END CI_Driver_Library CLASS + + +/** + * CodeIgniter Driver Class + * + * This class enables you to create drivers for a Library based on the Driver Library. + * It handles the drivers' access to the parent library + * + * @package CodeIgniter + * @subpackage Libraries + * @category Libraries + * @author EllisLab Dev Team + * @link + */ +class CI_Driver { + protected $parent; + + private $methods = array(); + private $properties = array(); + + private static $reflections = array(); + + /** + * Decorate + * + * Decorates the child with the parent driver lib's methods and properties + * + * @param object + * @return void + */ + public function decorate($parent) + { + $this->parent = $parent; + + // Lock down attributes to what is defined in the class + // and speed up references in magic methods + + $class_name = get_class($parent); + + if ( ! isset(self::$reflections[$class_name])) + { + $r = new ReflectionObject($parent); + + foreach ($r->getMethods() as $method) + { + if ($method->isPublic()) + { + $this->methods[] = $method->getName(); + } + } + + foreach ($r->getProperties() as $prop) + { + if ($prop->isPublic()) + { + $this->properties[] = $prop->getName(); + } + } + + self::$reflections[$class_name] = array($this->methods, $this->properties); + } + else + { + list($this->methods, $this->properties) = self::$reflections[$class_name]; + } + } + + // -------------------------------------------------------------------- + + /** + * __call magic method + * + * Handles access to the parent driver library's methods + * + * @access public + * @param string + * @param array + * @return mixed + */ + public function __call($method, $args = array()) + { + if (in_array($method, $this->methods)) + { + return call_user_func_array(array($this->parent, $method), $args); + } + + $trace = debug_backtrace(); + _exception_handler(E_ERROR, "No such method '{$method}'", $trace[1]['file'], $trace[1]['line']); + exit; + } + + // -------------------------------------------------------------------- + + /** + * __get magic method + * + * Handles reading of the parent driver library's properties + * + * @param string + * @return mixed + */ + public function __get($var) + { + if (in_array($var, $this->properties)) + { + return $this->parent->$var; + } + } + + // -------------------------------------------------------------------- + + /** + * __set magic method + * + * Handles writing to the parent driver library's properties + * + * @param string + * @param array + * @return mixed + */ + public function __set($var, $val) + { + if (in_array($var, $this->properties)) + { + $this->parent->$var = $val; + } + } + + // -------------------------------------------------------------------- + +} +// END CI_Driver CLASS + +/* End of file Driver.php */ +/* Location: ./system/libraries/Driver.php */ \ No newline at end of file diff --git a/system/libraries/Email.php b/system/libraries/Email.php new file mode 100644 index 0000000..9ec40af --- /dev/null +++ b/system/libraries/Email.php @@ -0,0 +1,2092 @@ + 0) + { + $this->initialize($config); + } + else + { + $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; + $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE; + } + + log_message('debug', "Email Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Initialize preferences + * + * @access public + * @param array + * @return void + */ + public function initialize($config = array()) + { + foreach ($config as $key => $val) + { + if (isset($this->$key)) + { + $method = 'set_'.$key; + + if (method_exists($this, $method)) + { + $this->$method($val); + } + else + { + $this->$key = $val; + } + } + } + $this->clear(); + + $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; + $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Initialize the Email Data + * + * @access public + * @return void + */ + public function clear($clear_attachments = FALSE) + { + $this->_subject = ""; + $this->_body = ""; + $this->_finalbody = ""; + $this->_header_str = ""; + $this->_replyto_flag = FALSE; + $this->_recipients = array(); + $this->_cc_array = array(); + $this->_bcc_array = array(); + $this->_headers = array(); + $this->_debug_msg = array(); + + $this->_set_header('User-Agent', $this->useragent); + $this->_set_header('Date', $this->_set_date()); + + if ($clear_attachments !== FALSE) + { + $this->_attach_name = array(); + $this->_attach_type = array(); + $this->_attach_disp = array(); + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set FROM + * + * @access public + * @param string + * @param string + * @return void + */ + public function from($from, $name = '') + { + if (preg_match( '/\<(.*)\>/', $from, $match)) + { + $from = $match['1']; + } + + if ($this->validate) + { + $this->validate_email($this->_str_to_array($from)); + } + + // prepare the display name + if ($name != '') + { + // only use Q encoding if there are characters that would require it + if ( ! preg_match('/[\200-\377]/', $name)) + { + // add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes + $name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"'; + } + else + { + $name = $this->_prep_q_encoding($name, TRUE); + } + } + + $this->_set_header('From', $name.' <'.$from.'>'); + $this->_set_header('Return-Path', '<'.$from.'>'); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Reply-to + * + * @access public + * @param string + * @param string + * @return void + */ + public function reply_to($replyto, $name = '') + { + if (preg_match( '/\<(.*)\>/', $replyto, $match)) + { + $replyto = $match['1']; + } + + if ($this->validate) + { + $this->validate_email($this->_str_to_array($replyto)); + } + + if ($name == '') + { + $name = $replyto; + } + + if (strncmp($name, '"', 1) != 0) + { + $name = '"'.$name.'"'; + } + + $this->_set_header('Reply-To', $name.' <'.$replyto.'>'); + $this->_replyto_flag = TRUE; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Recipients + * + * @access public + * @param string + * @return void + */ + public function to($to) + { + $to = $this->_str_to_array($to); + $to = $this->clean_email($to); + + if ($this->validate) + { + $this->validate_email($to); + } + + if ($this->_get_protocol() != 'mail') + { + $this->_set_header('To', implode(", ", $to)); + } + + switch ($this->_get_protocol()) + { + case 'smtp' : + $this->_recipients = $to; + break; + case 'sendmail' : + case 'mail' : + $this->_recipients = implode(", ", $to); + break; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set CC + * + * @access public + * @param string + * @return void + */ + public function cc($cc) + { + $cc = $this->_str_to_array($cc); + $cc = $this->clean_email($cc); + + if ($this->validate) + { + $this->validate_email($cc); + } + + $this->_set_header('Cc', implode(", ", $cc)); + + if ($this->_get_protocol() == "smtp") + { + $this->_cc_array = $cc; + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set BCC + * + * @access public + * @param string + * @param string + * @return void + */ + public function bcc($bcc, $limit = '') + { + if ($limit != '' && is_numeric($limit)) + { + $this->bcc_batch_mode = TRUE; + $this->bcc_batch_size = $limit; + } + + $bcc = $this->_str_to_array($bcc); + $bcc = $this->clean_email($bcc); + + if ($this->validate) + { + $this->validate_email($bcc); + } + + if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size)) + { + $this->_bcc_array = $bcc; + } + else + { + $this->_set_header('Bcc', implode(", ", $bcc)); + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Email Subject + * + * @access public + * @param string + * @return void + */ + public function subject($subject) + { + $subject = $this->_prep_q_encoding($subject); + $this->_set_header('Subject', $subject); + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Body + * + * @access public + * @param string + * @return void + */ + public function message($body) + { + $this->_body = rtrim(str_replace("\r", "", $body)); + + /* strip slashes only if magic quotes is ON + if we do it with magic quotes OFF, it strips real, user-inputted chars. + + NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and + it will probably not exist in future versions at all. + */ + if ( ! is_php('5.4') && get_magic_quotes_gpc()) + { + $this->_body = stripslashes($this->_body); + } + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Assign file attachments + * + * @access public + * @param string + * @return void + */ + public function attach($filename, $disposition = 'attachment') + { + $this->_attach_name[] = $filename; + $this->_attach_type[] = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION)); + $this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Add a Header Item + * + * @access protected + * @param string + * @param string + * @return void + */ + protected function _set_header($header, $value) + { + $this->_headers[$header] = $value; + } + + // -------------------------------------------------------------------- + + /** + * Convert a String to an Array + * + * @access protected + * @param string + * @return array + */ + protected function _str_to_array($email) + { + if ( ! is_array($email)) + { + if (strpos($email, ',') !== FALSE) + { + $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY); + } + else + { + $email = trim($email); + settype($email, "array"); + } + } + return $email; + } + + // -------------------------------------------------------------------- + + /** + * Set Multipart Value + * + * @access public + * @param string + * @return void + */ + public function set_alt_message($str = '') + { + $this->alt_message = $str; + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Mailtype + * + * @access public + * @param string + * @return void + */ + public function set_mailtype($type = 'text') + { + $this->mailtype = ($type == 'html') ? 'html' : 'text'; + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Wordwrap + * + * @access public + * @param string + * @return void + */ + public function set_wordwrap($wordwrap = TRUE) + { + $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE; + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Protocol + * + * @access public + * @param string + * @return void + */ + public function set_protocol($protocol = 'mail') + { + $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol); + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Priority + * + * @access public + * @param integer + * @return void + */ + public function set_priority($n = 3) + { + if ( ! is_numeric($n)) + { + $this->priority = 3; + return; + } + + if ($n < 1 OR $n > 5) + { + $this->priority = 3; + return; + } + + $this->priority = $n; + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Newline Character + * + * @access public + * @param string + * @return void + */ + public function set_newline($newline = "\n") + { + if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r") + { + $this->newline = "\n"; + return; + } + + $this->newline = $newline; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set CRLF + * + * @access public + * @param string + * @return void + */ + public function set_crlf($crlf = "\n") + { + if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r") + { + $this->crlf = "\n"; + return; + } + + $this->crlf = $crlf; + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Message Boundary + * + * @access protected + * @return void + */ + protected function _set_boundaries() + { + $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative + $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary + } + + // -------------------------------------------------------------------- + + /** + * Get the Message ID + * + * @access protected + * @return string + */ + protected function _get_message_id() + { + $from = $this->_headers['Return-Path']; + $from = str_replace(">", "", $from); + $from = str_replace("<", "", $from); + + return "<".uniqid('').strstr($from, '@').">"; + } + + // -------------------------------------------------------------------- + + /** + * Get Mail Protocol + * + * @access protected + * @param bool + * @return string + */ + protected function _get_protocol($return = TRUE) + { + $this->protocol = strtolower($this->protocol); + $this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol; + + if ($return == TRUE) + { + return $this->protocol; + } + } + + // -------------------------------------------------------------------- + + /** + * Get Mail Encoding + * + * @access protected + * @param bool + * @return string + */ + protected function _get_encoding($return = TRUE) + { + $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding; + + foreach ($this->_base_charsets as $charset) + { + if (strncmp($charset, $this->charset, strlen($charset)) == 0) + { + $this->_encoding = '7bit'; + } + } + + if ($return == TRUE) + { + return $this->_encoding; + } + } + + // -------------------------------------------------------------------- + + /** + * Get content type (text/html/attachment) + * + * @access protected + * @return string + */ + protected function _get_content_type() + { + if ($this->mailtype == 'html' && count($this->_attach_name) == 0) + { + return 'html'; + } + elseif ($this->mailtype == 'html' && count($this->_attach_name) > 0) + { + return 'html-attach'; + } + elseif ($this->mailtype == 'text' && count($this->_attach_name) > 0) + { + return 'plain-attach'; + } + else + { + return 'plain'; + } + } + + // -------------------------------------------------------------------- + + /** + * Set RFC 822 Date + * + * @access protected + * @return string + */ + protected function _set_date() + { + $timezone = date("Z"); + $operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+'; + $timezone = abs($timezone); + $timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60; + + return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone); + } + + // -------------------------------------------------------------------- + + /** + * Mime message + * + * @access protected + * @return string + */ + protected function _get_mime_message() + { + return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format."; + } + + // -------------------------------------------------------------------- + + /** + * Validate Email Address + * + * @access public + * @param string + * @return bool + */ + public function validate_email($email) + { + if ( ! is_array($email)) + { + $this->_set_error_message('lang:email_must_be_array'); + return FALSE; + } + + foreach ($email as $val) + { + if ( ! $this->valid_email($val)) + { + $this->_set_error_message('lang:email_invalid_address', $val); + return FALSE; + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Email Validation + * + * @access public + * @param string + * @return bool + */ + public function valid_email($address) + { + return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Clean Extended Email Address: Joe Smith + * + * @access public + * @param string + * @return string + */ + public function clean_email($email) + { + if ( ! is_array($email)) + { + if (preg_match('/\<(.*)\>/', $email, $match)) + { + return $match['1']; + } + else + { + return $email; + } + } + + $clean_email = array(); + + foreach ($email as $addy) + { + if (preg_match( '/\<(.*)\>/', $addy, $match)) + { + $clean_email[] = $match['1']; + } + else + { + $clean_email[] = $addy; + } + } + + return $clean_email; + } + + // -------------------------------------------------------------------- + + /** + * Build alternative plain text message + * + * This public function provides the raw message for use + * in plain-text headers of HTML-formatted emails. + * If the user hasn't specified his own alternative message + * it creates one by stripping the HTML + * + * @access protected + * @return string + */ + protected function _get_alt_message() + { + if ($this->alt_message != "") + { + return $this->word_wrap($this->alt_message, '76'); + } + + if (preg_match('/\(.*)\<\/body\>/si', $this->_body, $match)) + { + $body = $match['1']; + } + else + { + $body = $this->_body; + } + + $body = trim(strip_tags($body)); + $body = preg_replace( '# '.$msg."\n"; + + flock($fp, LOCK_EX); + fwrite($fp, $message); + flock($fp, LOCK_UN); + fclose($fp); + + @chmod($filepath, FILE_WRITE_MODE); + return TRUE; + } + +} +// END Log Class + +/* End of file Log.php */ +/* Location: ./system/libraries/Log.php */ \ No newline at end of file diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php new file mode 100644 index 0000000..df2dd7c --- /dev/null +++ b/system/libraries/Migration.php @@ -0,0 +1,328 @@ + $val) + { + $this->{'_' . $key} = $val; + } + + log_message('debug', 'Migrations class initialized'); + + // Are they trying to use migrations while it is disabled? + if ($this->_migration_enabled !== TRUE) + { + show_error('Migrations has been loaded but is disabled or set up incorrectly.'); + } + + // If not set, set it + $this->_migration_path == '' AND $this->_migration_path = APPPATH . 'migrations/'; + + // Add trailing slash if not set + $this->_migration_path = rtrim($this->_migration_path, '/').'/'; + + // Load migration language + $this->lang->load('migration'); + + // They'll probably be using dbforge + $this->load->dbforge(); + + // If the migrations table is missing, make it + if ( ! $this->db->table_exists('migrations')) + { + $this->dbforge->add_field(array( + 'version' => array('type' => 'INT', 'constraint' => 3), + )); + + $this->dbforge->create_table('migrations', TRUE); + + $this->db->insert('migrations', array('version' => 0)); + } + } + + // -------------------------------------------------------------------- + + /** + * Migrate to a schema version + * + * Calls each migration step required to get to the schema version of + * choice + * + * @param int Target schema version + * @return mixed TRUE if already latest, FALSE if failed, int if upgraded + */ + public function version($target_version) + { + $start = $current_version = $this->_get_version(); + $stop = $target_version; + + if ($target_version > $current_version) + { + // Moving Up + ++$start; + ++$stop; + $step = 1; + } + else + { + // Moving Down + $step = -1; + } + + $method = ($step === 1) ? 'up' : 'down'; + $migrations = array(); + + // We now prepare to actually DO the migrations + // But first let's make sure that everything is the way it should be + for ($i = $start; $i != $stop; $i += $step) + { + $f = glob(sprintf($this->_migration_path . '%03d_*.php', $i)); + + // Only one migration per step is permitted + if (count($f) > 1) + { + $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $i); + return FALSE; + } + + // Migration step not found + if (count($f) == 0) + { + // If trying to migrate up to a version greater than the last + // existing one, migrate to the last one. + if ($step == 1) + { + break; + } + + // If trying to migrate down but we're missing a step, + // something must definitely be wrong. + $this->_error_string = sprintf($this->lang->line('migration_not_found'), $i); + return FALSE; + } + + $file = basename($f[0]); + $name = basename($f[0], '.php'); + + // Filename validations + if (preg_match('/^\d{3}_(\w+)$/', $name, $match)) + { + $match[1] = strtolower($match[1]); + + // Cannot repeat a migration at different steps + if (in_array($match[1], $migrations)) + { + $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $match[1]); + return FALSE; + } + + include $f[0]; + $class = 'Migration_' . ucfirst($match[1]); + + if ( ! class_exists($class)) + { + $this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class); + return FALSE; + } + + if ( ! is_callable(array($class, $method))) + { + $this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class); + return FALSE; + } + + $migrations[] = $match[1]; + } + else + { + $this->_error_string = sprintf($this->lang->line('migration_invalid_filename'), $file); + return FALSE; + } + } + + log_message('debug', 'Current migration: ' . $current_version); + + $version = $i + ($step == 1 ? -1 : 0); + + // If there is nothing to do so quit + if ($migrations === array()) + { + return TRUE; + } + + log_message('debug', 'Migrating from ' . $method . ' to version ' . $version); + + // Loop through the migrations + foreach ($migrations AS $migration) + { + // Run the migration class + $class = 'Migration_' . ucfirst(strtolower($migration)); + call_user_func(array(new $class, $method)); + + $current_version += $step; + $this->_update_version($current_version); + } + + log_message('debug', 'Finished migrating to '.$current_version); + + return $current_version; + } + + // -------------------------------------------------------------------- + + /** + * Set's the schema to the latest migration + * + * @return mixed true if already latest, false if failed, int if upgraded + */ + public function latest() + { + if ( ! $migrations = $this->find_migrations()) + { + $this->_error_string = $this->line->lang('migration_none_found'); + return false; + } + + $last_migration = basename(end($migrations)); + + // Calculate the last migration step from existing migration + // filenames and procceed to the standard version migration + return $this->version((int) substr($last_migration, 0, 3)); + } + + // -------------------------------------------------------------------- + + /** + * Set's the schema to the migration version set in config + * + * @return mixed true if already current, false if failed, int if upgraded + */ + public function current() + { + return $this->version($this->_migration_version); + } + + // -------------------------------------------------------------------- + + /** + * Error string + * + * @return string Error message returned as a string + */ + public function error_string() + { + return $this->_error_string; + } + + // -------------------------------------------------------------------- + + /** + * Set's the schema to the latest migration + * + * @return mixed true if already latest, false if failed, int if upgraded + */ + protected function find_migrations() + { + // Load all *_*.php files in the migrations path + $files = glob($this->_migration_path . '*_*.php'); + $file_count = count($files); + + for ($i = 0; $i < $file_count; $i++) + { + // Mark wrongly formatted files as false for later filtering + $name = basename($files[$i], '.php'); + if ( ! preg_match('/^\d{3}_(\w+)$/', $name)) + { + $files[$i] = FALSE; + } + } + + sort($files); + return $files; + } + + // -------------------------------------------------------------------- + + /** + * Retrieves current schema version + * + * @return int Current Migration + */ + protected function _get_version() + { + $row = $this->db->get('migrations')->row(); + return $row ? $row->version : 0; + } + + // -------------------------------------------------------------------- + + /** + * Stores the current schema version + * + * @param int Migration reached + * @return bool + */ + protected function _update_version($migrations) + { + return $this->db->update('migrations', array( + 'version' => $migrations + )); + } + + // -------------------------------------------------------------------- + + /** + * Enable the use of CI super-global + * + * @param mixed $var + * @return mixed + */ + public function __get($var) + { + return get_instance()->$var; + } +} + +/* End of file Migration.php */ +/* Location: ./system/libraries/Migration.php */ \ No newline at end of file diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php new file mode 100644 index 0000000..cdaacf2 --- /dev/null +++ b/system/libraries/Pagination.php @@ -0,0 +1,340 @@ +'; + var $cur_tag_close = ''; + var $next_tag_open = ' '; + var $next_tag_close = ' '; + var $prev_tag_open = ' '; + var $prev_tag_close = ''; + var $num_tag_open = ' '; + var $num_tag_close = ''; + var $page_query_string = FALSE; + var $query_string_segment = 'per_page'; + var $display_pages = TRUE; + var $anchor_class = ''; + + /** + * Constructor + * + * @access public + * @param array initialization parameters + */ + public function __construct($params = array()) + { + if (count($params) > 0) + { + $this->initialize($params); + } + + if ($this->anchor_class != '') + { + $this->anchor_class = 'class="'.$this->anchor_class.'" '; + } + + log_message('debug', "Pagination Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Initialize Preferences + * + * @access public + * @param array initialization parameters + * @return void + */ + function initialize($params = array()) + { + if (count($params) > 0) + { + foreach ($params as $key => $val) + { + if (isset($this->$key)) + { + $this->$key = $val; + } + } + } + } + + // -------------------------------------------------------------------- + + /** + * Generate the pagination links + * + * @access public + * @return string + */ + function create_links() + { + // If our item count or per-page total is zero there is no need to continue. + if ($this->total_rows == 0 OR $this->per_page == 0) + { + return ''; + } + + // Calculate the total number of pages + $num_pages = ceil($this->total_rows / $this->per_page); + + // Is there only one page? Hm... nothing more to do here then. + if ($num_pages == 1) + { + return ''; + } + + // Set the base page index for starting page number + if ($this->use_page_numbers) + { + $base_page = 1; + } + else + { + $base_page = 0; + } + + // Determine the current page number. + $CI =& get_instance(); + + if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE) + { + if ($CI->input->get($this->query_string_segment) != $base_page) + { + $this->cur_page = $CI->input->get($this->query_string_segment); + + // Prep the current page - no funny business! + $this->cur_page = (int) $this->cur_page; + } + } + else + { + if ($CI->uri->segment($this->uri_segment) != $base_page) + { + $this->cur_page = $CI->uri->segment($this->uri_segment); + + // Prep the current page - no funny business! + $this->cur_page = (int) $this->cur_page; + } + } + + // Set current page to 1 if using page numbers instead of offset + if ($this->use_page_numbers AND $this->cur_page == 0) + { + $this->cur_page = $base_page; + } + + $this->num_links = (int)$this->num_links; + + if ($this->num_links < 1) + { + show_error('Your number of links must be a positive number.'); + } + + if ( ! is_numeric($this->cur_page)) + { + $this->cur_page = $base_page; + } + + // Is the page number beyond the result range? + // If so we show the last page + if ($this->use_page_numbers) + { + if ($this->cur_page > $num_pages) + { + $this->cur_page = $num_pages; + } + } + else + { + if ($this->cur_page > $this->total_rows) + { + $this->cur_page = ($num_pages - 1) * $this->per_page; + } + } + + $uri_page_number = $this->cur_page; + + if ( ! $this->use_page_numbers) + { + $this->cur_page = floor(($this->cur_page/$this->per_page) + 1); + } + + // Calculate the start and end numbers. These determine + // which number to start and end the digit links with + $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1; + $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages; + + // Is pagination being used over GET or POST? If get, add a per_page query + // string. If post, add a trailing slash to the base URL if needed + if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE) + { + $this->base_url = rtrim($this->base_url).'&'.$this->query_string_segment.'='; + } + else + { + $this->base_url = rtrim($this->base_url, '/') .'/'; + } + + // And here we go... + $output = ''; + + // Render the "First" link + if ($this->first_link !== FALSE AND $this->cur_page > ($this->num_links + 1)) + { + $first_url = ($this->first_url == '') ? $this->base_url : $this->first_url; + $output .= $this->first_tag_open.'anchor_class.'href="'.$first_url.'">'.$this->first_link.''.$this->first_tag_close; + } + + // Render the "previous" link + if ($this->prev_link !== FALSE AND $this->cur_page != 1) + { + if ($this->use_page_numbers) + { + $i = $uri_page_number - 1; + } + else + { + $i = $uri_page_number - $this->per_page; + } + + if ($i == 0 && $this->first_url != '') + { + $output .= $this->prev_tag_open.'anchor_class.'href="'.$this->first_url.'">'.$this->prev_link.''.$this->prev_tag_close; + } + else + { + $i = ($i == 0) ? '' : $this->prefix.$i.$this->suffix; + $output .= $this->prev_tag_open.'anchor_class.'href="'.$this->base_url.$i.'">'.$this->prev_link.''.$this->prev_tag_close; + } + + } + + // Render the pages + if ($this->display_pages !== FALSE) + { + // Write the digit links + for ($loop = $start -1; $loop <= $end; $loop++) + { + if ($this->use_page_numbers) + { + $i = $loop; + } + else + { + $i = ($loop * $this->per_page) - $this->per_page; + } + + if ($i >= $base_page) + { + if ($this->cur_page == $loop) + { + $output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page + } + else + { + $n = ($i == $base_page) ? '' : $i; + + if ($n == '' && $this->first_url != '') + { + $output .= $this->num_tag_open.'anchor_class.'href="'.$this->first_url.'">'.$loop.''.$this->num_tag_close; + } + else + { + $n = ($n == '') ? '' : $this->prefix.$n.$this->suffix; + + $output .= $this->num_tag_open.'anchor_class.'href="'.$this->base_url.$n.'">'.$loop.''.$this->num_tag_close; + } + } + } + } + } + + // Render the "next" link + if ($this->next_link !== FALSE AND $this->cur_page < $num_pages) + { + if ($this->use_page_numbers) + { + $i = $this->cur_page + 1; + } + else + { + $i = ($this->cur_page * $this->per_page); + } + + $output .= $this->next_tag_open.'anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'">'.$this->next_link.''.$this->next_tag_close; + } + + // Render the "Last" link + if ($this->last_link !== FALSE AND ($this->cur_page + $this->num_links) < $num_pages) + { + if ($this->use_page_numbers) + { + $i = $num_pages; + } + else + { + $i = (($num_pages * $this->per_page) - $this->per_page); + } + $output .= $this->last_tag_open.'anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'">'.$this->last_link.''.$this->last_tag_close; + } + + // Kill double slashes. Note: Sometimes we can end up with a double slash + // in the penultimate link so we'll kill all double slashes. + $output = preg_replace("#([^:])//+#", "\\1/", $output); + + // Add the wrapper HTML if exists + $output = $this->full_tag_open.$output.$this->full_tag_close; + + return $output; + } +} +// END Pagination Class + +/* End of file Pagination.php */ +/* Location: ./system/libraries/Pagination.php */ \ No newline at end of file diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php new file mode 100644 index 0000000..d223da0 --- /dev/null +++ b/system/libraries/Parser.php @@ -0,0 +1,212 @@ +load->view($template, $data, TRUE); + + return $this->_parse($template, $data, $return); + } + + // -------------------------------------------------------------------- + + /** + * Parse a String + * + * Parses pseudo-variables contained in the specified string, + * replacing them with the data in the second param + * + * @access public + * @param string + * @param array + * @param bool + * @return string + */ + function parse_string($template, $data, $return = FALSE) + { + return $this->_parse($template, $data, $return); + } + + // -------------------------------------------------------------------- + + /** + * Parse a template + * + * Parses pseudo-variables contained in the specified template, + * replacing them with the data in the second param + * + * @access public + * @param string + * @param array + * @param bool + * @return string + */ + function _parse($template, $data, $return = FALSE) + { + if ($template == '') + { + return FALSE; + } + + foreach ($data as $key => $val) + { + if (is_array($val)) + { + $template = $this->_parse_pair($key, $val, $template); + } + else + { + $template = $this->_parse_single($key, (string)$val, $template); + } + } + + if ($return == FALSE) + { + $CI =& get_instance(); + $CI->output->append_output($template); + } + + return $template; + } + + // -------------------------------------------------------------------- + + /** + * Set the left/right variable delimiters + * + * @access public + * @param string + * @param string + * @return void + */ + function set_delimiters($l = '{', $r = '}') + { + $this->l_delim = $l; + $this->r_delim = $r; + } + + // -------------------------------------------------------------------- + + /** + * Parse a single key/value + * + * @access private + * @param string + * @param string + * @param string + * @return string + */ + function _parse_single($key, $val, $string) + { + return str_replace($this->l_delim.$key.$this->r_delim, $val, $string); + } + + // -------------------------------------------------------------------- + + /** + * Parse a tag pair + * + * Parses tag pairs: {some_tag} string... {/some_tag} + * + * @access private + * @param string + * @param array + * @param string + * @return string + */ + function _parse_pair($variable, $data, $string) + { + if (FALSE === ($match = $this->_match_pair($string, $variable))) + { + return $string; + } + + $str = ''; + foreach ($data as $row) + { + $temp = $match['1']; + foreach ($row as $key => $val) + { + if ( ! is_array($val)) + { + $temp = $this->_parse_single($key, $val, $temp); + } + else + { + $temp = $this->_parse_pair($key, $val, $temp); + } + } + + $str .= $temp; + } + + return str_replace($match['0'], $str, $string); + } + + // -------------------------------------------------------------------- + + /** + * Matches a variable pair + * + * @access private + * @param string + * @param string + * @return mixed + */ + function _match_pair($string, $variable) + { + if ( ! preg_match("|" . preg_quote($this->l_delim) . $variable . preg_quote($this->r_delim) . "(.+?)". preg_quote($this->l_delim) . '/' . $variable . preg_quote($this->r_delim) . "|s", $string, $match)) + { + return FALSE; + } + + return $match; + } + +} +// END Parser Class + +/* End of file Parser.php */ +/* Location: ./system/libraries/Parser.php */ diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php new file mode 100644 index 0000000..882a82c --- /dev/null +++ b/system/libraries/Profiler.php @@ -0,0 +1,558 @@ +CI =& get_instance(); + $this->CI->load->language('profiler'); + + if (isset($config['query_toggle_count'])) + { + $this->_query_toggle_count = (int) $config['query_toggle_count']; + unset($config['query_toggle_count']); + } + + // default all sections to display + foreach ($this->_available_sections as $section) + { + if ( ! isset($config[$section])) + { + $this->_compile_{$section} = TRUE; + } + } + + $this->set_sections($config); + } + + // -------------------------------------------------------------------- + + /** + * Set Sections + * + * Sets the private _compile_* properties to enable/disable Profiler sections + * + * @param mixed + * @return void + */ + public function set_sections($config) + { + foreach ($config as $method => $enable) + { + if (in_array($method, $this->_available_sections)) + { + $this->_compile_{$method} = ($enable !== FALSE) ? TRUE : FALSE; + } + } + } + + // -------------------------------------------------------------------- + + /** + * Auto Profiler + * + * This function cycles through the entire array of mark points and + * matches any two points that are named identically (ending in "_start" + * and "_end" respectively). It then compiles the execution times for + * all points and returns it as an array + * + * @return array + */ + protected function _compile_benchmarks() + { + $profile = array(); + foreach ($this->CI->benchmark->marker as $key => $val) + { + // We match the "end" marker so that the list ends + // up in the order that it was defined + if (preg_match("/(.+?)_end/i", $key, $match)) + { + if (isset($this->CI->benchmark->marker[$match[1].'_end']) AND isset($this->CI->benchmark->marker[$match[1].'_start'])) + { + $profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key); + } + } + } + + // Build a table containing the profile data. + // Note: At some point we should turn this into a template that can + // be modified. We also might want to make this data available to be logged + + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_benchmarks').'  '; + $output .= "\n"; + $output .= "\n\n\n"; + + foreach ($profile as $key => $val) + { + $key = ucwords(str_replace(array('_', '-'), ' ', $key)); + $output .= "\n"; + } + + $output .= "
    ".$key."  ".$val."
    \n"; + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Compile Queries + * + * @return string + */ + protected function _compile_queries() + { + $dbs = array(); + + // Let's determine which databases are currently connected to + foreach (get_object_vars($this->CI) as $CI_object) + { + if (is_object($CI_object) && is_subclass_of(get_class($CI_object), 'CI_DB') ) + { + $dbs[] = $CI_object; + } + } + + if (count($dbs) == 0) + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_queries').'  '; + $output .= "\n"; + $output .= "\n\n\n"; + $output .="\n"; + $output .= "
    ".$this->CI->lang->line('profiler_no_db')."
    \n"; + $output .= "
    "; + + return $output; + } + + // Load the text helper so we can highlight the SQL + $this->CI->load->helper('text'); + + // Key words we want bolded + $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT JOIN', 'ORDER BY', 'GROUP BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR ', 'HAVING', 'OFFSET', 'NOT IN', 'IN', 'LIKE', 'NOT LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')'); + + $output = "\n\n"; + + $count = 0; + + foreach ($dbs as $db) + { + $count++; + + $hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : ''; + + $show_hide_js = '('.$this->CI->lang->line('profiler_section_hide').')'; + + if ($hide_queries != '') + { + $show_hide_js = '('.$this->CI->lang->line('profiler_section_show').')'; + } + + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_database').':  '.$db->database.'   '.$this->CI->lang->line('profiler_queries').': '.count($db->queries).'  '.$show_hide_js.''; + $output .= "\n"; + $output .= "\n\n\n"; + + if (count($db->queries) == 0) + { + $output .= "\n"; + } + else + { + foreach ($db->queries as $key => $val) + { + $time = number_format($db->query_times[$key], 4); + + $val = highlight_code($val, ENT_QUOTES); + + foreach ($highlight as $bold) + { + $val = str_replace($bold, ''.$bold.'', $val); + } + + $output .= "\n"; + } + } + + $output .= "
    ".$this->CI->lang->line('profiler_no_queries')."
    ".$time."  ".$val."
    \n"; + $output .= "
    "; + + } + + return $output; + } + + + // -------------------------------------------------------------------- + + /** + * Compile $_GET Data + * + * @return string + */ + protected function _compile_get() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_get_data').'  '; + $output .= "\n"; + + if (count($_GET) == 0) + { + $output .= "
    ".$this->CI->lang->line('profiler_no_get')."
    "; + } + else + { + $output .= "\n\n\n"; + + foreach ($_GET as $key => $val) + { + if ( ! is_numeric($key)) + { + $key = "'".$key."'"; + } + + $output .= "\n"; + } + + $output .= "
    $_GET[".$key."]   "; + if (is_array($val)) + { + $output .= "
    " . htmlspecialchars(stripslashes(print_r($val, true))) . "
    "; + } + else + { + $output .= htmlspecialchars(stripslashes($val)); + } + $output .= "
    \n"; + } + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Compile $_POST Data + * + * @return string + */ + protected function _compile_post() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_post_data').'  '; + $output .= "\n"; + + if (count($_POST) == 0) + { + $output .= "
    ".$this->CI->lang->line('profiler_no_post')."
    "; + } + else + { + $output .= "\n\n\n"; + + foreach ($_POST as $key => $val) + { + if ( ! is_numeric($key)) + { + $key = "'".$key."'"; + } + + $output .= "\n"; + } + + $output .= "
    $_POST[".$key."]   "; + if (is_array($val)) + { + $output .= "
    " . htmlspecialchars(stripslashes(print_r($val, TRUE))) . "
    "; + } + else + { + $output .= htmlspecialchars(stripslashes($val)); + } + $output .= "
    \n"; + } + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Show query string + * + * @return string + */ + protected function _compile_uri_string() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_uri_string').'  '; + $output .= "\n"; + + if ($this->CI->uri->uri_string == '') + { + $output .= "
    ".$this->CI->lang->line('profiler_no_uri')."
    "; + } + else + { + $output .= "
    ".$this->CI->uri->uri_string."
    "; + } + + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Show the controller and function that were called + * + * @return string + */ + protected function _compile_controller_info() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_controller_info').'  '; + $output .= "\n"; + + $output .= "
    ".$this->CI->router->fetch_class()."/".$this->CI->router->fetch_method()."
    "; + + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Compile memory usage + * + * Display total used memory + * + * @return string + */ + protected function _compile_memory_usage() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_memory_usage').'  '; + $output .= "\n"; + + if (function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '') + { + $output .= "
    ".number_format($usage).' bytes
    '; + } + else + { + $output .= "
    ".$this->CI->lang->line('profiler_no_memory')."
    "; + } + + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Compile header information + * + * Lists HTTP headers + * + * @return string + */ + protected function _compile_http_headers() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_headers').'  ('.$this->CI->lang->line('profiler_section_show').')'; + $output .= "\n"; + + $output .= "\n\n\n"; + + foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR') as $header) + { + $val = (isset($_SERVER[$header])) ? $_SERVER[$header] : ''; + $output .= "\n"; + } + + $output .= "\n"; + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Compile config information + * + * Lists developer config variables + * + * @return string + */ + protected function _compile_config() + { + $output = "\n\n"; + $output .= '
    '; + $output .= "\n"; + $output .= '  '.$this->CI->lang->line('profiler_config').'  ('.$this->CI->lang->line('profiler_section_show').')'; + $output .= "\n"; + + $output .= "\n\n\n"; + + foreach ($this->CI->config->config as $config=>$val) + { + if (is_array($val)) + { + $val = print_r($val, TRUE); + } + + $output .= "\n"; + } + + $output .= "\n"; + $output .= "
    "; + + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Compile session userdata + * + * @return string + */ + private function _compile_session_data() + { + if ( ! isset($this->CI->session)) + { + return; + } + + $output = '
    '; + $output .= '  '.$this->CI->lang->line('profiler_session_data').'  ('.$this->CI->lang->line('profiler_section_show').')'; + $output .= ""; + + foreach ($this->CI->session->all_userdata() as $key => $val) + { + if (is_array($val) OR is_object($val)) + { + $val = print_r($val, TRUE); + } + + $output .= "\n"; + } + + $output .= ''; + $output .= "
    "; + return $output; + } + + // -------------------------------------------------------------------- + + /** + * Run the Profiler + * + * @return string + */ + public function run() + { + $output = "
    "; + $fields_displayed = 0; + + foreach ($this->_available_sections as $section) + { + if ($this->_compile_{$section} !== FALSE) + { + $func = "_compile_{$section}"; + $output .= $this->{$func}(); + $fields_displayed++; + } + } + + if ($fields_displayed == 0) + { + $output .= '

    '.$this->CI->lang->line('profiler_no_profiles').'

    '; + } + + $output .= '
    '; + + return $output; + } +} + +// END CI_Profiler class + +/* End of file Profiler.php */ +/* Location: ./system/libraries/Profiler.php */ \ No newline at end of file diff --git a/system/libraries/Session.php b/system/libraries/Session.php new file mode 100644 index 0000000..891fdd3 --- /dev/null +++ b/system/libraries/Session.php @@ -0,0 +1,780 @@ +CI =& get_instance(); + + // Set all the session preferences, which can either be set + // manually via the $params array above or via the config file + foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key) + { + $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key); + } + + if ($this->encryption_key == '') + { + show_error('In order to use the Session class you are required to set an encryption key in your config file.'); + } + + // Load the string helper so we can use the strip_slashes() function + $this->CI->load->helper('string'); + + // Do we need encryption? If so, load the encryption class + if ($this->sess_encrypt_cookie == TRUE) + { + $this->CI->load->library('encrypt'); + } + + // Are we using a database? If so, load it + if ($this->sess_use_database === TRUE AND $this->sess_table_name != '') + { + $this->CI->load->database(); + } + + // Set the "now" time. Can either be GMT or server time, based on the + // config prefs. We use this to set the "last activity" time + $this->now = $this->_get_time(); + + // Set the session length. If the session expiration is + // set to zero we'll set the expiration two years from now. + if ($this->sess_expiration == 0) + { + $this->sess_expiration = (60*60*24*365*2); + } + + // Set the cookie name + $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name; + + // Run the Session routine. If a session doesn't exist we'll + // create a new one. If it does, we'll update it. + if ( ! $this->sess_read()) + { + $this->sess_create(); + } + else + { + $this->sess_update(); + } + + // Delete 'old' flashdata (from last request) + $this->_flashdata_sweep(); + + // Mark all new flashdata as old (data will be deleted before next request) + $this->_flashdata_mark(); + + // Delete expired sessions if necessary + $this->_sess_gc(); + + log_message('debug', "Session routines successfully run"); + } + + // -------------------------------------------------------------------- + + /** + * Fetch the current session data if it exists + * + * @access public + * @return bool + */ + function sess_read() + { + // Fetch the cookie + $session = $this->CI->input->cookie($this->sess_cookie_name); + + // No cookie? Goodbye cruel world!... + if ($session === FALSE) + { + log_message('debug', 'A session cookie was not found.'); + return FALSE; + } + + // Decrypt the cookie data + if ($this->sess_encrypt_cookie == TRUE) + { + $session = $this->CI->encrypt->decode($session); + } + else + { + // encryption was not used, so we need to check the md5 hash + $hash = substr($session, strlen($session)-32); // get last 32 chars + $session = substr($session, 0, strlen($session)-32); + + // Does the md5 hash match? This is to prevent manipulation of session data in userspace + if ($hash !== md5($session.$this->encryption_key)) + { + log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.'); + $this->sess_destroy(); + return FALSE; + } + } + + // Unserialize the session array + $session = $this->_unserialize($session); + + // Is the session data we unserialized an array with the correct format? + if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity'])) + { + $this->sess_destroy(); + return FALSE; + } + + // Is the session current? + if (($session['last_activity'] + $this->sess_expiration) < $this->now) + { + $this->sess_destroy(); + return FALSE; + } + + // Does the IP Match? + if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address()) + { + $this->sess_destroy(); + return FALSE; + } + + // Does the User Agent Match? + if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 120))) + { + $this->sess_destroy(); + return FALSE; + } + + // Is there a corresponding session in the DB? + if ($this->sess_use_database === TRUE) + { + $this->CI->db->where('session_id', $session['session_id']); + + if ($this->sess_match_ip == TRUE) + { + $this->CI->db->where('ip_address', $session['ip_address']); + } + + if ($this->sess_match_useragent == TRUE) + { + $this->CI->db->where('user_agent', $session['user_agent']); + } + + $query = $this->CI->db->get($this->sess_table_name); + + // No result? Kill it! + if ($query->num_rows() == 0) + { + $this->sess_destroy(); + return FALSE; + } + + // Is there custom data? If so, add it to the main session array + $row = $query->row(); + if (isset($row->user_data) AND $row->user_data != '') + { + $custom_data = $this->_unserialize($row->user_data); + + if (is_array($custom_data)) + { + foreach ($custom_data as $key => $val) + { + $session[$key] = $val; + } + } + } + } + + // Session is valid! + $this->userdata = $session; + unset($session); + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Write the session data + * + * @access public + * @return void + */ + function sess_write() + { + // Are we saving custom data to the DB? If not, all we do is update the cookie + if ($this->sess_use_database === FALSE) + { + $this->_set_cookie(); + return; + } + + // set the custom userdata, the session data we will set in a second + $custom_userdata = $this->userdata; + $cookie_userdata = array(); + + // Before continuing, we need to determine if there is any custom data to deal with. + // Let's determine this by removing the default indexes to see if there's anything left in the array + // and set the session data while we're at it + foreach (array('session_id','ip_address','user_agent','last_activity') as $val) + { + unset($custom_userdata[$val]); + $cookie_userdata[$val] = $this->userdata[$val]; + } + + // Did we find any custom data? If not, we turn the empty array into a string + // since there's no reason to serialize and store an empty array in the DB + if (count($custom_userdata) === 0) + { + $custom_userdata = ''; + } + else + { + // Serialize the custom data array so we can store it + $custom_userdata = $this->_serialize($custom_userdata); + } + + // Run the update query + $this->CI->db->where('session_id', $this->userdata['session_id']); + $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata)); + + // Write the cookie. Notice that we manually pass the cookie data array to the + // _set_cookie() function. Normally that function will store $this->userdata, but + // in this case that array contains custom data, which we do not want in the cookie. + $this->_set_cookie($cookie_userdata); + } + + // -------------------------------------------------------------------- + + /** + * Create a new session + * + * @access public + * @return void + */ + function sess_create() + { + $sessid = ''; + while (strlen($sessid) < 32) + { + $sessid .= mt_rand(0, mt_getrandmax()); + } + + // To make the session ID even more secure we'll combine it with the user's IP + $sessid .= $this->CI->input->ip_address(); + + $this->userdata = array( + 'session_id' => md5(uniqid($sessid, TRUE)), + 'ip_address' => $this->CI->input->ip_address(), + 'user_agent' => substr($this->CI->input->user_agent(), 0, 120), + 'last_activity' => $this->now, + 'user_data' => '' + ); + + + // Save the data to the DB if needed + if ($this->sess_use_database === TRUE) + { + $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata)); + } + + // Write the cookie + $this->_set_cookie(); + } + + // -------------------------------------------------------------------- + + /** + * Update an existing session + * + * @access public + * @return void + */ + function sess_update() + { + // We only update the session every five minutes by default + if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now) + { + return; + } + + // Save the old session id so we know which record to + // update in the database if we need it + $old_sessid = $this->userdata['session_id']; + $new_sessid = ''; + while (strlen($new_sessid) < 32) + { + $new_sessid .= mt_rand(0, mt_getrandmax()); + } + + // To make the session ID even more secure we'll combine it with the user's IP + $new_sessid .= $this->CI->input->ip_address(); + + // Turn it into a hash + $new_sessid = md5(uniqid($new_sessid, TRUE)); + + // Update the session data in the session data array + $this->userdata['session_id'] = $new_sessid; + $this->userdata['last_activity'] = $this->now; + + // _set_cookie() will handle this for us if we aren't using database sessions + // by pushing all userdata to the cookie. + $cookie_data = NULL; + + // Update the session ID and last_activity field in the DB if needed + if ($this->sess_use_database === TRUE) + { + // set cookie explicitly to only have our session data + $cookie_data = array(); + foreach (array('session_id','ip_address','user_agent','last_activity') as $val) + { + $cookie_data[$val] = $this->userdata[$val]; + } + + $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid))); + } + + // Write the cookie + $this->_set_cookie($cookie_data); + } + + // -------------------------------------------------------------------- + + /** + * Destroy the current session + * + * @access public + * @return void + */ + function sess_destroy() + { + // Kill the session DB row + if ($this->sess_use_database === TRUE && isset($this->userdata['session_id'])) + { + $this->CI->db->where('session_id', $this->userdata['session_id']); + $this->CI->db->delete($this->sess_table_name); + } + + // Kill the cookie + setcookie( + $this->sess_cookie_name, + addslashes(serialize(array())), + ($this->now - 31500000), + $this->cookie_path, + $this->cookie_domain, + 0 + ); + + // Kill session data + $this->userdata = array(); + } + + // -------------------------------------------------------------------- + + /** + * Fetch a specific item from the session array + * + * @access public + * @param string + * @return string + */ + function userdata($item) + { + return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item]; + } + + // -------------------------------------------------------------------- + + /** + * Fetch all session data + * + * @access public + * @return array + */ + function all_userdata() + { + return $this->userdata; + } + + // -------------------------------------------------------------------- + + /** + * Add or change data in the "userdata" array + * + * @access public + * @param mixed + * @param string + * @return void + */ + function set_userdata($newdata = array(), $newval = '') + { + if (is_string($newdata)) + { + $newdata = array($newdata => $newval); + } + + if (count($newdata) > 0) + { + foreach ($newdata as $key => $val) + { + $this->userdata[$key] = $val; + } + } + + $this->sess_write(); + } + + // -------------------------------------------------------------------- + + /** + * Delete a session variable from the "userdata" array + * + * @access array + * @return void + */ + function unset_userdata($newdata = array()) + { + if (is_string($newdata)) + { + $newdata = array($newdata => ''); + } + + if (count($newdata) > 0) + { + foreach ($newdata as $key => $val) + { + unset($this->userdata[$key]); + } + } + + $this->sess_write(); + } + + // ------------------------------------------------------------------------ + + /** + * Add or change flashdata, only available + * until the next request + * + * @access public + * @param mixed + * @param string + * @return void + */ + function set_flashdata($newdata = array(), $newval = '') + { + if (is_string($newdata)) + { + $newdata = array($newdata => $newval); + } + + if (count($newdata) > 0) + { + foreach ($newdata as $key => $val) + { + $flashdata_key = $this->flashdata_key.':new:'.$key; + $this->set_userdata($flashdata_key, $val); + } + } + } + + // ------------------------------------------------------------------------ + + /** + * Keeps existing flashdata available to next request. + * + * @access public + * @param string + * @return void + */ + function keep_flashdata($key) + { + // 'old' flashdata gets removed. Here we mark all + // flashdata as 'new' to preserve it from _flashdata_sweep() + // Note the function will return FALSE if the $key + // provided cannot be found + $old_flashdata_key = $this->flashdata_key.':old:'.$key; + $value = $this->userdata($old_flashdata_key); + + $new_flashdata_key = $this->flashdata_key.':new:'.$key; + $this->set_userdata($new_flashdata_key, $value); + } + + // ------------------------------------------------------------------------ + + /** + * Fetch a specific flashdata item from the session array + * + * @access public + * @param string + * @return string + */ + function flashdata($key) + { + $flashdata_key = $this->flashdata_key.':old:'.$key; + return $this->userdata($flashdata_key); + } + + // ------------------------------------------------------------------------ + + /** + * Identifies flashdata as 'old' for removal + * when _flashdata_sweep() runs. + * + * @access private + * @return void + */ + function _flashdata_mark() + { + $userdata = $this->all_userdata(); + foreach ($userdata as $name => $value) + { + $parts = explode(':new:', $name); + if (is_array($parts) && count($parts) === 2) + { + $new_name = $this->flashdata_key.':old:'.$parts[1]; + $this->set_userdata($new_name, $value); + $this->unset_userdata($name); + } + } + } + + // ------------------------------------------------------------------------ + + /** + * Removes all flashdata marked as 'old' + * + * @access private + * @return void + */ + + function _flashdata_sweep() + { + $userdata = $this->all_userdata(); + foreach ($userdata as $key => $value) + { + if (strpos($key, ':old:')) + { + $this->unset_userdata($key); + } + } + + } + + // -------------------------------------------------------------------- + + /** + * Get the "now" time + * + * @access private + * @return string + */ + function _get_time() + { + if (strtolower($this->time_reference) == 'gmt') + { + $now = time(); + $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now)); + } + else + { + $time = time(); + } + + return $time; + } + + // -------------------------------------------------------------------- + + /** + * Write the session cookie + * + * @access public + * @return void + */ + function _set_cookie($cookie_data = NULL) + { + if (is_null($cookie_data)) + { + $cookie_data = $this->userdata; + } + + // Serialize the userdata for the cookie + $cookie_data = $this->_serialize($cookie_data); + + if ($this->sess_encrypt_cookie == TRUE) + { + $cookie_data = $this->CI->encrypt->encode($cookie_data); + } + else + { + // if encryption is not used, we provide an md5 hash to prevent userside tampering + $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key); + } + + $expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time(); + + // Set the cookie + setcookie( + $this->sess_cookie_name, + $cookie_data, + $expire, + $this->cookie_path, + $this->cookie_domain, + $this->cookie_secure + ); + } + + // -------------------------------------------------------------------- + + /** + * Serialize an array + * + * This function first converts any slashes found in the array to a temporary + * marker, so when it gets unserialized the slashes will be preserved + * + * @access private + * @param array + * @return string + */ + function _serialize($data) + { + if (is_array($data)) + { + foreach ($data as $key => $val) + { + if (is_string($val)) + { + $data[$key] = str_replace('\\', '{{slash}}', $val); + } + } + } + else + { + if (is_string($data)) + { + $data = str_replace('\\', '{{slash}}', $data); + } + } + + return serialize($data); + } + + // -------------------------------------------------------------------- + + /** + * Unserialize + * + * This function unserializes a data string, then converts any + * temporary slash markers back to actual slashes + * + * @access private + * @param array + * @return string + */ + function _unserialize($data) + { + $data = @unserialize(strip_slashes($data)); + + if (is_array($data)) + { + foreach ($data as $key => $val) + { + if (is_string($val)) + { + $data[$key] = str_replace('{{slash}}', '\\', $val); + } + } + + return $data; + } + + return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data; + } + + // -------------------------------------------------------------------- + + /** + * Garbage collection + * + * This deletes expired session rows from database + * if the probability percentage is met + * + * @access public + * @return void + */ + function _sess_gc() + { + if ($this->sess_use_database != TRUE) + { + return; + } + + srand(time()); + if ((rand() % 100) < $this->gc_probability) + { + $expire = $this->now - $this->sess_expiration; + + $this->CI->db->where("last_activity < {$expire}"); + $this->CI->db->delete($this->sess_table_name); + + log_message('debug', 'Session garbage collection performed.'); + } + } + + +} +// END Session Class + +/* End of file Session.php */ +/* Location: ./system/libraries/Session.php */ \ No newline at end of file diff --git a/system/libraries/Sha1.php b/system/libraries/Sha1.php new file mode 100644 index 0000000..1a65757 --- /dev/null +++ b/system/libraries/Sha1.php @@ -0,0 +1,251 @@ +> 6) + 1; + + for ($i = 0; $i < $n * 16; $i++) + { + $x[$i] = 0; + } + + for ($i = 0; $i < strlen($str); $i++) + { + $x[$i >> 2] |= ord(substr($str, $i, 1)) << (24 - ($i % 4) * 8); + } + + $x[$i >> 2] |= 0x80 << (24 - ($i % 4) * 8); + + $x[$n * 16 - 1] = strlen($str) * 8; + + $a = 1732584193; + $b = -271733879; + $c = -1732584194; + $d = 271733878; + $e = -1009589776; + + for ($i = 0; $i < count($x); $i += 16) + { + $olda = $a; + $oldb = $b; + $oldc = $c; + $oldd = $d; + $olde = $e; + + for ($j = 0; $j < 80; $j++) + { + if ($j < 16) + { + $w[$j] = $x[$i + $j]; + } + else + { + $w[$j] = $this->_rol($w[$j - 3] ^ $w[$j - 8] ^ $w[$j - 14] ^ $w[$j - 16], 1); + } + + $t = $this->_safe_add($this->_safe_add($this->_rol($a, 5), $this->_ft($j, $b, $c, $d)), $this->_safe_add($this->_safe_add($e, $w[$j]), $this->_kt($j))); + + $e = $d; + $d = $c; + $c = $this->_rol($b, 30); + $b = $a; + $a = $t; + } + + $a = $this->_safe_add($a, $olda); + $b = $this->_safe_add($b, $oldb); + $c = $this->_safe_add($c, $oldc); + $d = $this->_safe_add($d, $oldd); + $e = $this->_safe_add($e, $olde); + } + + return $this->_hex($a).$this->_hex($b).$this->_hex($c).$this->_hex($d).$this->_hex($e); + } + + // -------------------------------------------------------------------- + + /** + * Convert a decimal to hex + * + * @access private + * @param string + * @return string + */ + function _hex($str) + { + $str = dechex($str); + + if (strlen($str) == 7) + { + $str = '0'.$str; + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Return result based on iteration + * + * @access private + * @return string + */ + function _ft($t, $b, $c, $d) + { + if ($t < 20) + return ($b & $c) | ((~$b) & $d); + if ($t < 40) + return $b ^ $c ^ $d; + if ($t < 60) + return ($b & $c) | ($b & $d) | ($c & $d); + + return $b ^ $c ^ $d; + } + + // -------------------------------------------------------------------- + + /** + * Determine the additive constant + * + * @access private + * @return string + */ + function _kt($t) + { + if ($t < 20) + { + return 1518500249; + } + else if ($t < 40) + { + return 1859775393; + } + else if ($t < 60) + { + return -1894007588; + } + else + { + return -899497514; + } + } + + // -------------------------------------------------------------------- + + /** + * Add integers, wrapping at 2^32 + * + * @access private + * @return string + */ + function _safe_add($x, $y) + { + $lsw = ($x & 0xFFFF) + ($y & 0xFFFF); + $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16); + + return ($msw << 16) | ($lsw & 0xFFFF); + } + + // -------------------------------------------------------------------- + + /** + * Bitwise rotate a 32-bit number + * + * @access private + * @return integer + */ + function _rol($num, $cnt) + { + return ($num << $cnt) | $this->_zero_fill($num, 32 - $cnt); + } + + // -------------------------------------------------------------------- + + /** + * Pad string with zero + * + * @access private + * @return string + */ + function _zero_fill($a, $b) + { + $bin = decbin($a); + + if (strlen($bin) < $b) + { + $bin = 0; + } + else + { + $bin = substr($bin, 0, strlen($bin) - $b); + } + + for ($i=0; $i < $b; $i++) + { + $bin = "0".$bin; + } + + return bindec($bin); + } +} +// END CI_SHA + +/* End of file Sha1.php */ +/* Location: ./system/libraries/Sha1.php */ \ No newline at end of file diff --git a/system/libraries/Table.php b/system/libraries/Table.php new file mode 100644 index 0000000..def6967 --- /dev/null +++ b/system/libraries/Table.php @@ -0,0 +1,531 @@ +template = $template; + } + + // -------------------------------------------------------------------- + + /** + * Set the table heading + * + * Can be passed as an array or discreet params + * + * @access public + * @param mixed + * @return void + */ + function set_heading() + { + $args = func_get_args(); + $this->heading = $this->_prep_args($args); + } + + // -------------------------------------------------------------------- + + /** + * Set columns. Takes a one-dimensional array as input and creates + * a multi-dimensional array with a depth equal to the number of + * columns. This allows a single array with many elements to be + * displayed in a table that has a fixed column count. + * + * @access public + * @param array + * @param int + * @return void + */ + function make_columns($array = array(), $col_limit = 0) + { + if ( ! is_array($array) OR count($array) == 0) + { + return FALSE; + } + + // Turn off the auto-heading feature since it's doubtful we + // will want headings from a one-dimensional array + $this->auto_heading = FALSE; + + if ($col_limit == 0) + { + return $array; + } + + $new = array(); + while (count($array) > 0) + { + $temp = array_splice($array, 0, $col_limit); + + if (count($temp) < $col_limit) + { + for ($i = count($temp); $i < $col_limit; $i++) + { + $temp[] = ' '; + } + } + + $new[] = $temp; + } + + return $new; + } + + // -------------------------------------------------------------------- + + /** + * Set "empty" cells + * + * Can be passed as an array or discreet params + * + * @access public + * @param mixed + * @return void + */ + function set_empty($value) + { + $this->empty_cells = $value; + } + + // -------------------------------------------------------------------- + + /** + * Add a table row + * + * Can be passed as an array or discreet params + * + * @access public + * @param mixed + * @return void + */ + function add_row() + { + $args = func_get_args(); + $this->rows[] = $this->_prep_args($args); + } + + // -------------------------------------------------------------------- + + /** + * Prep Args + * + * Ensures a standard associative array format for all cell data + * + * @access public + * @param type + * @return type + */ + function _prep_args($args) + { + // If there is no $args[0], skip this and treat as an associative array + // This can happen if there is only a single key, for example this is passed to table->generate + // array(array('foo'=>'bar')) + if (isset($args[0]) AND (count($args) == 1 && is_array($args[0]))) + { + // args sent as indexed array + if ( ! isset($args[0]['data'])) + { + foreach ($args[0] as $key => $val) + { + if (is_array($val) && isset($val['data'])) + { + $args[$key] = $val; + } + else + { + $args[$key] = array('data' => $val); + } + } + } + } + else + { + foreach ($args as $key => $val) + { + if ( ! is_array($val)) + { + $args[$key] = array('data' => $val); + } + } + } + + return $args; + } + + // -------------------------------------------------------------------- + + /** + * Add a table caption + * + * @access public + * @param string + * @return void + */ + function set_caption($caption) + { + $this->caption = $caption; + } + + // -------------------------------------------------------------------- + + /** + * Generate the table + * + * @access public + * @param mixed + * @return string + */ + function generate($table_data = NULL) + { + // The table data can optionally be passed to this function + // either as a database result object or an array + if ( ! is_null($table_data)) + { + if (is_object($table_data)) + { + $this->_set_from_object($table_data); + } + elseif (is_array($table_data)) + { + $set_heading = (count($this->heading) == 0 AND $this->auto_heading == FALSE) ? FALSE : TRUE; + $this->_set_from_array($table_data, $set_heading); + } + } + + // Is there anything to display? No? Smite them! + if (count($this->heading) == 0 AND count($this->rows) == 0) + { + return 'Undefined table data'; + } + + // Compile and validate the template date + $this->_compile_template(); + + // set a custom cell manipulation function to a locally scoped variable so its callable + $function = $this->function; + + // Build the table! + + $out = $this->template['table_open']; + $out .= $this->newline; + + // Add any caption here + if ($this->caption) + { + $out .= $this->newline; + $out .= '' . $this->caption . ''; + $out .= $this->newline; + } + + // Is there a table heading to display? + if (count($this->heading) > 0) + { + $out .= $this->template['thead_open']; + $out .= $this->newline; + $out .= $this->template['heading_row_start']; + $out .= $this->newline; + + foreach ($this->heading as $heading) + { + $temp = $this->template['heading_cell_start']; + + foreach ($heading as $key => $val) + { + if ($key != 'data') + { + $temp = str_replace('template['heading_cell_end']; + } + + $out .= $this->template['heading_row_end']; + $out .= $this->newline; + $out .= $this->template['thead_close']; + $out .= $this->newline; + } + + // Build the table rows + if (count($this->rows) > 0) + { + $out .= $this->template['tbody_open']; + $out .= $this->newline; + + $i = 1; + foreach ($this->rows as $row) + { + if ( ! is_array($row)) + { + break; + } + + // We use modulus to alternate the row colors + $name = (fmod($i++, 2)) ? '' : 'alt_'; + + $out .= $this->template['row_'.$name.'start']; + $out .= $this->newline; + + foreach ($row as $cell) + { + $temp = $this->template['cell_'.$name.'start']; + + foreach ($cell as $key => $val) + { + if ($key != 'data') + { + $temp = str_replace('empty_cells; + } + else + { + if ($function !== FALSE && is_callable($function)) + { + $out .= call_user_func($function, $cell); + } + else + { + $out .= $cell; + } + } + + $out .= $this->template['cell_'.$name.'end']; + } + + $out .= $this->template['row_'.$name.'end']; + $out .= $this->newline; + } + + $out .= $this->template['tbody_close']; + $out .= $this->newline; + } + + $out .= $this->template['table_close']; + + // Clear table class properties before generating the table + $this->clear(); + + return $out; + } + + // -------------------------------------------------------------------- + + /** + * Clears the table arrays. Useful if multiple tables are being generated + * + * @access public + * @return void + */ + function clear() + { + $this->rows = array(); + $this->heading = array(); + $this->auto_heading = TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Set table data from a database result object + * + * @access public + * @param object + * @return void + */ + function _set_from_object($query) + { + if ( ! is_object($query)) + { + return FALSE; + } + + // First generate the headings from the table column names + if (count($this->heading) == 0) + { + if ( ! method_exists($query, 'list_fields')) + { + return FALSE; + } + + $this->heading = $this->_prep_args($query->list_fields()); + } + + // Next blast through the result array and build out the rows + + if ($query->num_rows() > 0) + { + foreach ($query->result_array() as $row) + { + $this->rows[] = $this->_prep_args($row); + } + } + } + + // -------------------------------------------------------------------- + + /** + * Set table data from an array + * + * @access public + * @param array + * @return void + */ + function _set_from_array($data, $set_heading = TRUE) + { + if ( ! is_array($data) OR count($data) == 0) + { + return FALSE; + } + + $i = 0; + foreach ($data as $row) + { + // If a heading hasn't already been set we'll use the first row of the array as the heading + if ($i == 0 AND count($data) > 1 AND count($this->heading) == 0 AND $set_heading == TRUE) + { + $this->heading = $this->_prep_args($row); + } + else + { + $this->rows[] = $this->_prep_args($row); + } + + $i++; + } + } + + // -------------------------------------------------------------------- + + /** + * Compile Template + * + * @access private + * @return void + */ + function _compile_template() + { + if ($this->template == NULL) + { + $this->template = $this->_default_template(); + return; + } + + $this->temp = $this->_default_template(); + foreach (array('table_open', 'thead_open', 'thead_close', 'heading_row_start', 'heading_row_end', 'heading_cell_start', 'heading_cell_end', 'tbody_open', 'tbody_close', 'row_start', 'row_end', 'cell_start', 'cell_end', 'row_alt_start', 'row_alt_end', 'cell_alt_start', 'cell_alt_end', 'table_close') as $val) + { + if ( ! isset($this->template[$val])) + { + $this->template[$val] = $this->temp[$val]; + } + } + } + + // -------------------------------------------------------------------- + + /** + * Default Template + * + * @access private + * @return void + */ + function _default_template() + { + return array ( + 'table_open' => '', + + 'thead_open' => '', + 'thead_close' => '', + + 'heading_row_start' => '', + 'heading_row_end' => '', + 'heading_cell_start' => '', + + 'tbody_open' => '', + 'tbody_close' => '', + + 'row_start' => '', + 'row_end' => '', + 'cell_start' => '', + + 'row_alt_start' => '', + 'row_alt_end' => '', + 'cell_alt_start' => '', + + 'table_close' => '
    ', + 'heading_cell_end' => '
    ', + 'cell_end' => '
    ', + 'cell_alt_end' => '
    ' + ); + } + + +} + + +/* End of file Table.php */ +/* Location: ./system/libraries/Table.php */ \ No newline at end of file diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php new file mode 100644 index 0000000..b0a7678 --- /dev/null +++ b/system/libraries/Trackback.php @@ -0,0 +1,548 @@ + '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => ''); + var $convert_ascii = TRUE; + var $response = ''; + var $error_msg = array(); + + /** + * Constructor + * + * @access public + */ + public function __construct() + { + log_message('debug', "Trackback Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Send Trackback + * + * @access public + * @param array + * @return bool + */ + function send($tb_data) + { + if ( ! is_array($tb_data)) + { + $this->set_error('The send() method must be passed an array'); + return FALSE; + } + + // Pre-process the Trackback Data + foreach (array('url', 'title', 'excerpt', 'blog_name', 'ping_url') as $item) + { + if ( ! isset($tb_data[$item])) + { + $this->set_error('Required item missing: '.$item); + return FALSE; + } + + switch ($item) + { + case 'ping_url' : $$item = $this->extract_urls($tb_data[$item]); + break; + case 'excerpt' : $$item = $this->limit_characters($this->convert_xml(strip_tags(stripslashes($tb_data[$item])))); + break; + case 'url' : $$item = str_replace('-', '-', $this->convert_xml(strip_tags(stripslashes($tb_data[$item])))); + break; + default : $$item = $this->convert_xml(strip_tags(stripslashes($tb_data[$item]))); + break; + } + + // Convert High ASCII Characters + if ($this->convert_ascii == TRUE) + { + if ($item == 'excerpt') + { + $$item = $this->convert_ascii($$item); + } + elseif ($item == 'title') + { + $$item = $this->convert_ascii($$item); + } + elseif ($item == 'blog_name') + { + $$item = $this->convert_ascii($$item); + } + } + } + + // Build the Trackback data string + $charset = ( ! isset($tb_data['charset'])) ? $this->charset : $tb_data['charset']; + + $data = "url=".rawurlencode($url)."&title=".rawurlencode($title)."&blog_name=".rawurlencode($blog_name)."&excerpt=".rawurlencode($excerpt)."&charset=".rawurlencode($charset); + + // Send Trackback(s) + $return = TRUE; + if (count($ping_url) > 0) + { + foreach ($ping_url as $url) + { + if ($this->process($url, $data) == FALSE) + { + $return = FALSE; + } + } + } + + return $return; + } + + // -------------------------------------------------------------------- + + /** + * Receive Trackback Data + * + * This function simply validates the incoming TB data. + * It returns FALSE on failure and TRUE on success. + * If the data is valid it is set to the $this->data array + * so that it can be inserted into a database. + * + * @access public + * @return bool + */ + function receive() + { + foreach (array('url', 'title', 'blog_name', 'excerpt') as $val) + { + if ( ! isset($_POST[$val]) OR $_POST[$val] == '') + { + $this->set_error('The following required POST variable is missing: '.$val); + return FALSE; + } + + $this->data['charset'] = ( ! isset($_POST['charset'])) ? 'auto' : strtoupper(trim($_POST['charset'])); + + if ($val != 'url' && function_exists('mb_convert_encoding')) + { + $_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']); + } + + $_POST[$val] = ($val != 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]); + + if ($val == 'excerpt') + { + $_POST['excerpt'] = $this->limit_characters($_POST['excerpt']); + } + + $this->data[$val] = $_POST[$val]; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Send Trackback Error Message + * + * Allows custom errors to be set. By default it + * sends the "incomplete information" error, as that's + * the most common one. + * + * @access public + * @param string + * @return void + */ + function send_error($message = 'Incomplete Information') + { + echo "\n\n1\n".$message."\n"; + exit; + } + + // -------------------------------------------------------------------- + + /** + * Send Trackback Success Message + * + * This should be called when a trackback has been + * successfully received and inserted. + * + * @access public + * @return void + */ + function send_success() + { + echo "\n\n0\n"; + exit; + } + + // -------------------------------------------------------------------- + + /** + * Fetch a particular item + * + * @access public + * @param string + * @return string + */ + function data($item) + { + return ( ! isset($this->data[$item])) ? '' : $this->data[$item]; + } + + // -------------------------------------------------------------------- + + /** + * Process Trackback + * + * Opens a socket connection and passes the data to + * the server. Returns TRUE on success, FALSE on failure + * + * @access public + * @param string + * @param string + * @return bool + */ + function process($url, $data) + { + $target = parse_url($url); + + // Open the socket + if ( ! $fp = @fsockopen($target['host'], 80)) + { + $this->set_error('Invalid Connection: '.$url); + return FALSE; + } + + // Build the path + $ppath = ( ! isset($target['path'])) ? $url : $target['path']; + + $path = (isset($target['query']) && $target['query'] != "") ? $ppath.'?'.$target['query'] : $ppath; + + // Add the Trackback ID to the data string + if ($id = $this->get_id($url)) + { + $data = "tb_id=".$id."&".$data; + } + + // Transfer the data + fputs ($fp, "POST " . $path . " HTTP/1.0\r\n" ); + fputs ($fp, "Host: " . $target['host'] . "\r\n" ); + fputs ($fp, "Content-type: application/x-www-form-urlencoded\r\n" ); + fputs ($fp, "Content-length: " . strlen($data) . "\r\n" ); + fputs ($fp, "Connection: close\r\n\r\n" ); + fputs ($fp, $data); + + // Was it successful? + $this->response = ""; + + while ( ! feof($fp)) + { + $this->response .= fgets($fp, 128); + } + @fclose($fp); + + + if (stristr($this->response, '0') === FALSE) + { + $message = 'An unknown error was encountered'; + + if (preg_match("/(.*?)<\/message>/is", $this->response, $match)) + { + $message = trim($match['1']); + } + + $this->set_error($message); + return FALSE; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Extract Trackback URLs + * + * This function lets multiple trackbacks be sent. + * It takes a string of URLs (separated by comma or + * space) and puts each URL into an array + * + * @access public + * @param string + * @return string + */ + function extract_urls($urls) + { + // Remove the pesky white space and replace with a comma. + $urls = preg_replace("/\s*(\S+)\s*/", "\\1,", $urls); + + // If they use commas get rid of the doubles. + $urls = str_replace(",,", ",", $urls); + + // Remove any comma that might be at the end + if (substr($urls, -1) == ",") + { + $urls = substr($urls, 0, -1); + } + + // Break into an array via commas + $urls = preg_split('/[,]/', $urls); + + // Removes duplicates + $urls = array_unique($urls); + + array_walk($urls, array($this, 'validate_url')); + + return $urls; + } + + // -------------------------------------------------------------------- + + /** + * Validate URL + * + * Simply adds "http://" if missing + * + * @access public + * @param string + * @return string + */ + function validate_url($url) + { + $url = trim($url); + + if (substr($url, 0, 4) != "http") + { + $url = "http://".$url; + } + } + + // -------------------------------------------------------------------- + + /** + * Find the Trackback URL's ID + * + * @access public + * @param string + * @return string + */ + function get_id($url) + { + $tb_id = ""; + + if (strpos($url, '?') !== FALSE) + { + $tb_array = explode('/', $url); + $tb_end = $tb_array[count($tb_array)-1]; + + if ( ! is_numeric($tb_end)) + { + $tb_end = $tb_array[count($tb_array)-2]; + } + + $tb_array = explode('=', $tb_end); + $tb_id = $tb_array[count($tb_array)-1]; + } + else + { + $url = rtrim($url, '/'); + + $tb_array = explode('/', $url); + $tb_id = $tb_array[count($tb_array)-1]; + + if ( ! is_numeric($tb_id)) + { + $tb_id = $tb_array[count($tb_array)-2]; + } + } + + if ( ! preg_match ("/^([0-9]+)$/", $tb_id)) + { + return FALSE; + } + else + { + return $tb_id; + } + } + + // -------------------------------------------------------------------- + + /** + * Convert Reserved XML characters to Entities + * + * @access public + * @param string + * @return string + */ + function convert_xml($str) + { + $temp = '__TEMP_AMPERSANDS__'; + + $str = preg_replace("/&#(\d+);/", "$temp\\1;", $str); + $str = preg_replace("/&(\w+);/", "$temp\\1;", $str); + + $str = str_replace(array("&","<",">","\"", "'", "-"), + array("&", "<", ">", """, "'", "-"), + $str); + + $str = preg_replace("/$temp(\d+);/","&#\\1;",$str); + $str = preg_replace("/$temp(\w+);/","&\\1;", $str); + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Character limiter + * + * Limits the string based on the character count. Will preserve complete words. + * + * @access public + * @param string + * @param integer + * @param string + * @return string + */ + function limit_characters($str, $n = 500, $end_char = '…') + { + if (strlen($str) < $n) + { + return $str; + } + + $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str)); + + if (strlen($str) <= $n) + { + return $str; + } + + $out = ""; + foreach (explode(' ', trim($str)) as $val) + { + $out .= $val.' '; + if (strlen($out) >= $n) + { + return trim($out).$end_char; + } + } + } + + // -------------------------------------------------------------------- + + /** + * High ASCII to Entities + * + * Converts Hight ascii text and MS Word special chars + * to character entities + * + * @access public + * @param string + * @return string + */ + function convert_ascii($str) + { + $count = 1; + $out = ''; + $temp = array(); + + for ($i = 0, $s = strlen($str); $i < $s; $i++) + { + $ordinal = ord($str[$i]); + + if ($ordinal < 128) + { + $out .= $str[$i]; + } + else + { + if (count($temp) == 0) + { + $count = ($ordinal < 224) ? 2 : 3; + } + + $temp[] = $ordinal; + + if (count($temp) == $count) + { + $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64); + + $out .= '&#'.$number.';'; + $count = 1; + $temp = array(); + } + } + } + + return $out; + } + + // -------------------------------------------------------------------- + + /** + * Set error message + * + * @access public + * @param string + * @return void + */ + function set_error($msg) + { + log_message('error', $msg); + $this->error_msg[] = $msg; + } + + // -------------------------------------------------------------------- + + /** + * Show error messages + * + * @access public + * @param string + * @param string + * @return string + */ + function display_errors($open = '

    ', $close = '

    ') + { + $str = ''; + foreach ($this->error_msg as $val) + { + $str .= $open.$val.$close; + } + + return $str; + } + +} +// END Trackback Class + +/* End of file Trackback.php */ +/* Location: ./system/libraries/Trackback.php */ \ No newline at end of file diff --git a/system/libraries/Typography.php b/system/libraries/Typography.php new file mode 100644 index 0000000..734cec1 --- /dev/null +++ b/system/libraries/Typography.php @@ -0,0 +1,410 @@ + tags + var $block_elements = 'address|blockquote|div|dl|fieldset|form|h\d|hr|noscript|object|ol|p|pre|script|table|ul'; + + // Elements that should not have

    and
    tags within them. + var $skip_elements = 'p|pre|ol|ul|dl|object|table|h\d'; + + // Tags we want the parser to completely ignore when splitting the string. + var $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var'; + + // array of block level elements that require inner content to be within another block level element + var $inner_block_required = array('blockquote'); + + // the last block element parsed + var $last_block_element = ''; + + // whether or not to protect quotes within { curly braces } + var $protect_braced_quotes = FALSE; + + /** + * Auto Typography + * + * This function converts text, making it typographically correct: + * - Converts double spaces into paragraphs. + * - Converts single line breaks into
    tags + * - Converts single and double quotes into correctly facing curly quote entities. + * - Converts three dots into ellipsis. + * - Converts double dashes into em-dashes. + * - Converts two spaces into entities + * + * @access public + * @param string + * @param bool whether to reduce more then two consecutive newlines to two + * @return string + */ + function auto_typography($str, $reduce_linebreaks = FALSE) + { + if ($str == '') + { + return ''; + } + + // Standardize Newlines to make matching easier + if (strpos($str, "\r") !== FALSE) + { + $str = str_replace(array("\r\n", "\r"), "\n", $str); + } + + // Reduce line breaks. If there are more than two consecutive linebreaks + // we'll compress them down to a maximum of two since there's no benefit to more. + if ($reduce_linebreaks === TRUE) + { + $str = preg_replace("/\n\n+/", "\n\n", $str); + } + + // HTML comment tags don't conform to patterns of normal tags, so pull them out separately, only if needed + $html_comments = array(); + if (strpos($str, '", + "'", + "<", + ">", + '"', + '&', + '$', + '=', + ';', + '?', + '/', + "%20", + "%22", + "%3c", // < + "%253c", // < + "%3e", // > + "%0e", // > + "%28", // ( + "%29", // ) + "%2528", // ( + "%26", // & + "%24", // $ + "%3f", // ? + "%3b", // ; + "%3d" // = + ); + + $filename = str_replace($bad, '', $filename); + + return stripslashes($filename); + } + + // -------------------------------------------------------------------- + + /** + * Limit the File Name Length + * + * @param string + * @return string + */ + public function limit_filename_length($filename, $length) + { + if (strlen($filename) < $length) + { + return $filename; + } + + $ext = ''; + if (strpos($filename, '.') !== FALSE) + { + $parts = explode('.', $filename); + $ext = '.'.array_pop($parts); + $filename = implode('.', $parts); + } + + return substr($filename, 0, ($length - strlen($ext))).$ext; + } + + // -------------------------------------------------------------------- + + /** + * Runs the file through the XSS clean function + * + * This prevents people from embedding malicious code in their files. + * I'm not sure that it won't negatively affect certain files in unexpected ways, + * but so far I haven't found that it causes trouble. + * + * @return void + */ + public function do_xss_clean() + { + $file = $this->file_temp; + + if (filesize($file) == 0) + { + return FALSE; + } + + if (function_exists('memory_get_usage') && memory_get_usage() && ini_get('memory_limit') != '') + { + $current = ini_get('memory_limit') * 1024 * 1024; + + // There was a bug/behavioural change in PHP 5.2, where numbers over one million get output + // into scientific notation. number_format() ensures this number is an integer + // http://bugs.php.net/bug.php?id=43053 + + $new_memory = number_format(ceil(filesize($file) + $current), 0, '.', ''); + + ini_set('memory_limit', $new_memory); // When an integer is used, the value is measured in bytes. - PHP.net + } + + // If the file being uploaded is an image, then we should have no problem with XSS attacks (in theory), but + // IE can be fooled into mime-type detecting a malformed image as an html file, thus executing an XSS attack on anyone + // using IE who looks at the image. It does this by inspecting the first 255 bytes of an image. To get around this + // CI will itself look at the first 255 bytes of an image to determine its relative safety. This can save a lot of + // processor power and time if it is actually a clean image, as it will be in nearly all instances _except_ an + // attempted XSS attack. + + if (function_exists('getimagesize') && @getimagesize($file) !== FALSE) + { + if (($file = @fopen($file, 'rb')) === FALSE) // "b" to force binary + { + return FALSE; // Couldn't open the file, return FALSE + } + + $opening_bytes = fread($file, 256); + fclose($file); + + // These are known to throw IE into mime-type detection chaos + // ]/i', $opening_bytes)) + { + return TRUE; // its an image, no "triggers" detected in the first 256 bytes, we're good + } + else + { + return FALSE; + } + } + + if (($data = @file_get_contents($file)) === FALSE) + { + return FALSE; + } + + $CI =& get_instance(); + return $CI->security->xss_clean($data, TRUE); + } + + // -------------------------------------------------------------------- + + /** + * Set an error message + * + * @param string + * @return void + */ + public function set_error($msg) + { + $CI =& get_instance(); + $CI->lang->load('upload'); + + if (is_array($msg)) + { + foreach ($msg as $val) + { + $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val); + $this->error_msg[] = $msg; + log_message('error', $msg); + } + } + else + { + $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg); + $this->error_msg[] = $msg; + log_message('error', $msg); + } + } + + // -------------------------------------------------------------------- + + /** + * Display the error message + * + * @param string + * @param string + * @return string + */ + public function display_errors($open = '

    ', $close = '

    ') + { + $str = ''; + foreach ($this->error_msg as $val) + { + $str .= $open.$val.$close; + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * List of Mime Types + * + * This is a list of mime types. We use it to validate + * the "allowed types" set by the developer + * + * @param string + * @return string + */ + public function mimes_types($mime) + { + global $mimes; + + if (count($this->mimes) == 0) + { + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'); + } + elseif (is_file(APPPATH.'config/mimes.php')) + { + include(APPPATH.'config//mimes.php'); + } + else + { + return FALSE; + } + + $this->mimes = $mimes; + unset($mimes); + } + + return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime]; + } + + // -------------------------------------------------------------------- + + /** + * Prep Filename + * + * Prevents possible script execution from Apache's handling of files multiple extensions + * http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext + * + * @param string + * @return string + */ + protected function _prep_filename($filename) + { + if (strpos($filename, '.') === FALSE OR $this->allowed_types == '*') + { + return $filename; + } + + $parts = explode('.', $filename); + $ext = array_pop($parts); + $filename = array_shift($parts); + + foreach ($parts as $part) + { + if ( ! in_array(strtolower($part), $this->allowed_types) OR $this->mimes_types(strtolower($part)) === FALSE) + { + $filename .= '.'.$part.'_'; + } + else + { + $filename .= '.'.$part; + } + } + + $filename .= '.'.$ext; + + return $filename; + } + + // -------------------------------------------------------------------- + + /** + * File MIME type + * + * Detects the (actual) MIME type of the uploaded file, if possible. + * The input array is expected to be $_FILES[$field] + * + * @param array + * @return void + */ + protected function _file_mime_type($file) + { + // We'll need this to validate the MIME info string (e.g. text/plain; charset=us-ascii) + $regexp = '/^([a-z\-]+\/[a-z0-9\-\.\+]+)(;\s.+)?$/'; + + /* Fileinfo extension - most reliable method + * + * Unfortunately, prior to PHP 5.3 - it's only available as a PECL extension and the + * more convenient FILEINFO_MIME_TYPE flag doesn't exist. + */ + if (function_exists('finfo_file')) + { + $finfo = finfo_open(FILEINFO_MIME); + if (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system + { + $mime = @finfo_file($finfo, $file['tmp_name']); + finfo_close($finfo); + + /* According to the comments section of the PHP manual page, + * it is possible that this function returns an empty string + * for some files (e.g. if they don't exist in the magic MIME database) + */ + if (is_string($mime) && preg_match($regexp, $mime, $matches)) + { + $this->file_type = $matches[1]; + return; + } + } + } + + /* This is an ugly hack, but UNIX-type systems provide a "native" way to detect the file type, + * which is still more secure than depending on the value of $_FILES[$field]['type'], and as it + * was reported in issue #750 (https://github.com/EllisLab/CodeIgniter/issues/750) - it's better + * than mime_content_type() as well, hence the attempts to try calling the command line with + * three different functions. + * + * Notes: + * - the DIRECTORY_SEPARATOR comparison ensures that we're not on a Windows system + * - many system admins would disable the exec(), shell_exec(), popen() and similar functions + * due to security concerns, hence the function_exists() checks + */ + if (DIRECTORY_SEPARATOR !== '\\') + { + $cmd = 'file --brief --mime ' . escapeshellarg($file['tmp_name']) . ' 2>&1'; + + if (function_exists('exec')) + { + /* This might look confusing, as $mime is being populated with all of the output when set in the second parameter. + * However, we only neeed the last line, which is the actual return value of exec(), and as such - it overwrites + * anything that could already be set for $mime previously. This effectively makes the second parameter a dummy + * value, which is only put to allow us to get the return status code. + */ + $mime = @exec($cmd, $mime, $return_status); + if ($return_status === 0 && is_string($mime) && preg_match($regexp, $mime, $matches)) + { + $this->file_type = $matches[1]; + return; + } + } + + if ( (bool) @ini_get('safe_mode') === FALSE && function_exists('shell_exec')) + { + $mime = @shell_exec($cmd); + if (strlen($mime) > 0) + { + $mime = explode("\n", trim($mime)); + if (preg_match($regexp, $mime[(count($mime) - 1)], $matches)) + { + $this->file_type = $matches[1]; + return; + } + } + } + + if (function_exists('popen')) + { + $proc = @popen($cmd, 'r'); + if (is_resource($proc)) + { + $mime = @fread($proc, 512); + @pclose($proc); + if ($mime !== FALSE) + { + $mime = explode("\n", trim($mime)); + if (preg_match($regexp, $mime[(count($mime) - 1)], $matches)) + { + $this->file_type = $matches[1]; + return; + } + } + } + } + } + + // Fall back to the deprecated mime_content_type(), if available (still better than $_FILES[$field]['type']) + if (function_exists('mime_content_type')) + { + $this->file_type = @mime_content_type($file['tmp_name']); + if (strlen($this->file_type) > 0) // It's possible that mime_content_type() returns FALSE or an empty string + { + return; + } + } + + $this->file_type = $file['type']; + } + + // -------------------------------------------------------------------- + +} +// END Upload Class + +/* End of file Upload.php */ +/* Location: ./system/libraries/Upload.php */ diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php new file mode 100644 index 0000000..0b77a7d --- /dev/null +++ b/system/libraries/User_agent.php @@ -0,0 +1,549 @@ +agent = trim($_SERVER['HTTP_USER_AGENT']); + } + + if ( ! is_null($this->agent)) + { + if ($this->_load_agent_file()) + { + $this->_compile_data(); + } + } + + log_message('debug', "User Agent Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Compile the User Agent Data + * + * @access private + * @return bool + */ + private function _load_agent_file() + { + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'); + } + elseif (is_file(APPPATH.'config/user_agents.php')) + { + include(APPPATH.'config/user_agents.php'); + } + else + { + return FALSE; + } + + $return = FALSE; + + if (isset($platforms)) + { + $this->platforms = $platforms; + unset($platforms); + $return = TRUE; + } + + if (isset($browsers)) + { + $this->browsers = $browsers; + unset($browsers); + $return = TRUE; + } + + if (isset($mobiles)) + { + $this->mobiles = $mobiles; + unset($mobiles); + $return = TRUE; + } + + if (isset($robots)) + { + $this->robots = $robots; + unset($robots); + $return = TRUE; + } + + return $return; + } + + // -------------------------------------------------------------------- + + /** + * Compile the User Agent Data + * + * @access private + * @return bool + */ + private function _compile_data() + { + $this->_set_platform(); + + foreach (array('_set_robot', '_set_browser', '_set_mobile') as $function) + { + if ($this->$function() === TRUE) + { + break; + } + } + } + + // -------------------------------------------------------------------- + + /** + * Set the Platform + * + * @access private + * @return mixed + */ + private function _set_platform() + { + if (is_array($this->platforms) AND count($this->platforms) > 0) + { + foreach ($this->platforms as $key => $val) + { + if (preg_match("|".preg_quote($key)."|i", $this->agent)) + { + $this->platform = $val; + return TRUE; + } + } + } + $this->platform = 'Unknown Platform'; + } + + // -------------------------------------------------------------------- + + /** + * Set the Browser + * + * @access private + * @return bool + */ + private function _set_browser() + { + if (is_array($this->browsers) AND count($this->browsers) > 0) + { + foreach ($this->browsers as $key => $val) + { + if (preg_match("|".preg_quote($key).".*?([0-9\.]+)|i", $this->agent, $match)) + { + $this->is_browser = TRUE; + $this->version = $match[1]; + $this->browser = $val; + $this->_set_mobile(); + return TRUE; + } + } + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Set the Robot + * + * @access private + * @return bool + */ + private function _set_robot() + { + if (is_array($this->robots) AND count($this->robots) > 0) + { + foreach ($this->robots as $key => $val) + { + if (preg_match("|".preg_quote($key)."|i", $this->agent)) + { + $this->is_robot = TRUE; + $this->robot = $val; + return TRUE; + } + } + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Set the Mobile Device + * + * @access private + * @return bool + */ + private function _set_mobile() + { + if (is_array($this->mobiles) AND count($this->mobiles) > 0) + { + foreach ($this->mobiles as $key => $val) + { + if (FALSE !== (strpos(strtolower($this->agent), $key))) + { + $this->is_mobile = TRUE; + $this->mobile = $val; + return TRUE; + } + } + } + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Set the accepted languages + * + * @access private + * @return void + */ + private function _set_languages() + { + if ((count($this->languages) == 0) AND isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) AND $_SERVER['HTTP_ACCEPT_LANGUAGE'] != '') + { + $languages = preg_replace('/(;q=[0-9\.]+)/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE']))); + + $this->languages = explode(',', $languages); + } + + if (count($this->languages) == 0) + { + $this->languages = array('Undefined'); + } + } + + // -------------------------------------------------------------------- + + /** + * Set the accepted character sets + * + * @access private + * @return void + */ + private function _set_charsets() + { + if ((count($this->charsets) == 0) AND isset($_SERVER['HTTP_ACCEPT_CHARSET']) AND $_SERVER['HTTP_ACCEPT_CHARSET'] != '') + { + $charsets = preg_replace('/(;q=.+)/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET']))); + + $this->charsets = explode(',', $charsets); + } + + if (count($this->charsets) == 0) + { + $this->charsets = array('Undefined'); + } + } + + // -------------------------------------------------------------------- + + /** + * Is Browser + * + * @access public + * @return bool + */ + public function is_browser($key = NULL) + { + if ( ! $this->is_browser) + { + return FALSE; + } + + // No need to be specific, it's a browser + if ($key === NULL) + { + return TRUE; + } + + // Check for a specific browser + return array_key_exists($key, $this->browsers) AND $this->browser === $this->browsers[$key]; + } + + // -------------------------------------------------------------------- + + /** + * Is Robot + * + * @access public + * @return bool + */ + public function is_robot($key = NULL) + { + if ( ! $this->is_robot) + { + return FALSE; + } + + // No need to be specific, it's a robot + if ($key === NULL) + { + return TRUE; + } + + // Check for a specific robot + return array_key_exists($key, $this->robots) AND $this->robot === $this->robots[$key]; + } + + // -------------------------------------------------------------------- + + /** + * Is Mobile + * + * @access public + * @return bool + */ + public function is_mobile($key = NULL) + { + if ( ! $this->is_mobile) + { + return FALSE; + } + + // No need to be specific, it's a mobile + if ($key === NULL) + { + return TRUE; + } + + // Check for a specific robot + return array_key_exists($key, $this->mobiles) AND $this->mobile === $this->mobiles[$key]; + } + + // -------------------------------------------------------------------- + + /** + * Is this a referral from another site? + * + * @access public + * @return bool + */ + public function is_referral() + { + if ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '') + { + return FALSE; + } + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Agent String + * + * @access public + * @return string + */ + public function agent_string() + { + return $this->agent; + } + + // -------------------------------------------------------------------- + + /** + * Get Platform + * + * @access public + * @return string + */ + public function platform() + { + return $this->platform; + } + + // -------------------------------------------------------------------- + + /** + * Get Browser Name + * + * @access public + * @return string + */ + public function browser() + { + return $this->browser; + } + + // -------------------------------------------------------------------- + + /** + * Get the Browser Version + * + * @access public + * @return string + */ + public function version() + { + return $this->version; + } + + // -------------------------------------------------------------------- + + /** + * Get The Robot Name + * + * @access public + * @return string + */ + public function robot() + { + return $this->robot; + } + // -------------------------------------------------------------------- + + /** + * Get the Mobile Device + * + * @access public + * @return string + */ + public function mobile() + { + return $this->mobile; + } + + // -------------------------------------------------------------------- + + /** + * Get the referrer + * + * @access public + * @return bool + */ + public function referrer() + { + return ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '') ? '' : trim($_SERVER['HTTP_REFERER']); + } + + // -------------------------------------------------------------------- + + /** + * Get the accepted languages + * + * @access public + * @return array + */ + public function languages() + { + if (count($this->languages) == 0) + { + $this->_set_languages(); + } + + return $this->languages; + } + + // -------------------------------------------------------------------- + + /** + * Get the accepted Character Sets + * + * @access public + * @return array + */ + public function charsets() + { + if (count($this->charsets) == 0) + { + $this->_set_charsets(); + } + + return $this->charsets; + } + + // -------------------------------------------------------------------- + + /** + * Test for a particular language + * + * @access public + * @return bool + */ + public function accept_lang($lang = 'en') + { + return (in_array(strtolower($lang), $this->languages(), TRUE)); + } + + // -------------------------------------------------------------------- + + /** + * Test for a particular character set + * + * @access public + * @return bool + */ + public function accept_charset($charset = 'utf-8') + { + return (in_array(strtolower($charset), $this->charsets(), TRUE)); + } + +} + + +/* End of file User_agent.php */ +/* Location: ./system/libraries/User_agent.php */ \ No newline at end of file diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php new file mode 100644 index 0000000..d702e90 --- /dev/null +++ b/system/libraries/Xmlrpc.php @@ -0,0 +1,1423 @@ +xmlrpcName = $this->xmlrpcName; + $this->xmlrpc_backslash = chr(92).chr(92); + + // Types for info sent back and forth + $this->xmlrpcTypes = array( + $this->xmlrpcI4 => '1', + $this->xmlrpcInt => '1', + $this->xmlrpcBoolean => '1', + $this->xmlrpcString => '1', + $this->xmlrpcDouble => '1', + $this->xmlrpcDateTime => '1', + $this->xmlrpcBase64 => '1', + $this->xmlrpcArray => '2', + $this->xmlrpcStruct => '3' + ); + + // Array of Valid Parents for Various XML-RPC elements + $this->valid_parents = array('BOOLEAN' => array('VALUE'), + 'I4' => array('VALUE'), + 'INT' => array('VALUE'), + 'STRING' => array('VALUE'), + 'DOUBLE' => array('VALUE'), + 'DATETIME.ISO8601' => array('VALUE'), + 'BASE64' => array('VALUE'), + 'ARRAY' => array('VALUE'), + 'STRUCT' => array('VALUE'), + 'PARAM' => array('PARAMS'), + 'METHODNAME' => array('METHODCALL'), + 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), + 'MEMBER' => array('STRUCT'), + 'NAME' => array('MEMBER'), + 'DATA' => array('ARRAY'), + 'FAULT' => array('METHODRESPONSE'), + 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT') + ); + + + // XML-RPC Responses + $this->xmlrpcerr['unknown_method'] = '1'; + $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server'; + $this->xmlrpcerr['invalid_return'] = '2'; + $this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.'; + $this->xmlrpcerr['incorrect_params'] = '3'; + $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method'; + $this->xmlrpcerr['introspect_unknown'] = '4'; + $this->xmlrpcstr['introspect_unknown'] = "Cannot inspect signature for request: method unknown"; + $this->xmlrpcerr['http_error'] = '5'; + $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server."; + $this->xmlrpcerr['no_data'] = '6'; + $this->xmlrpcstr['no_data'] ='No data received from server.'; + + $this->initialize($config); + + log_message('debug', "XML-RPC Class Initialized"); + } + + + //------------------------------------- + // Initialize Prefs + //------------------------------------- + + function initialize($config = array()) + { + if (count($config) > 0) + { + foreach ($config as $key => $val) + { + if (isset($this->$key)) + { + $this->$key = $val; + } + } + } + } + // END + + //------------------------------------- + // Take URL and parse it + //------------------------------------- + + function server($url, $port=80) + { + if (substr($url, 0, 4) != "http") + { + $url = "http://".$url; + } + + $parts = parse_url($url); + + $path = ( ! isset($parts['path'])) ? '/' : $parts['path']; + + if (isset($parts['query']) && $parts['query'] != '') + { + $path .= '?'.$parts['query']; + } + + $this->client = new XML_RPC_Client($path, $parts['host'], $port); + } + // END + + //------------------------------------- + // Set Timeout + //------------------------------------- + + function timeout($seconds=5) + { + if ( ! is_null($this->client) && is_int($seconds)) + { + $this->client->timeout = $seconds; + } + } + // END + + //------------------------------------- + // Set Methods + //------------------------------------- + + function method($function) + { + $this->method = $function; + } + // END + + //------------------------------------- + // Take Array of Data and Create Objects + //------------------------------------- + + function request($incoming) + { + if ( ! is_array($incoming)) + { + // Send Error + } + + $this->data = array(); + + foreach ($incoming as $key => $value) + { + $this->data[$key] = $this->values_parsing($value); + } + } + // END + + + //------------------------------------- + // Set Debug + //------------------------------------- + + function set_debug($flag = TRUE) + { + $this->debug = ($flag == TRUE) ? TRUE : FALSE; + } + + //------------------------------------- + // Values Parsing + //------------------------------------- + + function values_parsing($value, $return = FALSE) + { + if (is_array($value) && array_key_exists(0, $value)) + { + if ( ! isset($value['1']) OR ( ! isset($this->xmlrpcTypes[$value['1']]))) + { + if (is_array($value[0])) + { + $temp = new XML_RPC_Values($value['0'], 'array'); + } + else + { + $temp = new XML_RPC_Values($value['0'], 'string'); + } + } + elseif (is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array')) + { + while (list($k) = each($value['0'])) + { + $value['0'][$k] = $this->values_parsing($value['0'][$k], TRUE); + } + + $temp = new XML_RPC_Values($value['0'], $value['1']); + } + else + { + $temp = new XML_RPC_Values($value['0'], $value['1']); + } + } + else + { + $temp = new XML_RPC_Values($value, 'string'); + } + + return $temp; + } + // END + + + //------------------------------------- + // Sends XML-RPC Request + //------------------------------------- + + function send_request() + { + $this->message = new XML_RPC_Message($this->method,$this->data); + $this->message->debug = $this->debug; + + if ( ! $this->result = $this->client->send($this->message)) + { + $this->error = $this->result->errstr; + return FALSE; + } + elseif ( ! is_object($this->result->val)) + { + $this->error = $this->result->errstr; + return FALSE; + } + + $this->response = $this->result->decode(); + + return TRUE; + } + // END + + //------------------------------------- + // Returns Error + //------------------------------------- + + function display_error() + { + return $this->error; + } + // END + + //------------------------------------- + // Returns Remote Server Response + //------------------------------------- + + function display_response() + { + return $this->response; + } + // END + + //------------------------------------- + // Sends an Error Message for Server Request + //------------------------------------- + + function send_error_message($number, $message) + { + return new XML_RPC_Response('0',$number, $message); + } + // END + + + //------------------------------------- + // Send Response for Server Request + //------------------------------------- + + function send_response($response) + { + // $response should be array of values, which will be parsed + // based on their data and type into a valid group of XML-RPC values + + $response = $this->values_parsing($response); + + return new XML_RPC_Response($response); + } + // END + +} // END XML_RPC Class + + + +/** + * XML-RPC Client class + * + * @category XML-RPC + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html + */ +class XML_RPC_Client extends CI_Xmlrpc +{ + var $path = ''; + var $server = ''; + var $port = 80; + var $errno = ''; + var $errstring = ''; + var $timeout = 5; + var $no_multicall = FALSE; + + public function __construct($path, $server, $port=80) + { + parent::__construct(); + + $this->port = $port; + $this->server = $server; + $this->path = $path; + } + + function send($msg) + { + if (is_array($msg)) + { + // Multi-call disabled + $r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'],$this->xmlrpcstr['multicall_recursion']); + return $r; + } + + return $this->sendPayload($msg); + } + + function sendPayload($msg) + { + $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout); + + if ( ! is_resource($fp)) + { + error_log($this->xmlrpcstr['http_error']); + $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'],$this->xmlrpcstr['http_error']); + return $r; + } + + if (empty($msg->payload)) + { + // $msg = XML_RPC_Messages + $msg->createPayload(); + } + + $r = "\r\n"; + $op = "POST {$this->path} HTTP/1.0$r"; + $op .= "Host: {$this->server}$r"; + $op .= "Content-Type: text/xml$r"; + $op .= "User-Agent: {$this->xmlrpcName}$r"; + $op .= "Content-Length: ".strlen($msg->payload). "$r$r"; + $op .= $msg->payload; + + + if ( ! fputs($fp, $op, strlen($op))) + { + error_log($this->xmlrpcstr['http_error']); + $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']); + return $r; + } + $resp = $msg->parseResponse($fp); + fclose($fp); + return $resp; + } + +} // end class XML_RPC_Client + + +/** + * XML-RPC Response class + * + * @category XML-RPC + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html + */ +class XML_RPC_Response +{ + var $val = 0; + var $errno = 0; + var $errstr = ''; + var $headers = array(); + var $xss_clean = TRUE; + + public function __construct($val, $code = 0, $fstr = '') + { + if ($code != 0) + { + // error + $this->errno = $code; + $this->errstr = htmlentities($fstr); + } + else if ( ! is_object($val)) + { + // programmer error, not an object + error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to XML_RPC_Response. Defaulting to empty value."); + $this->val = new XML_RPC_Values(); + } + else + { + $this->val = $val; + } + } + + function faultCode() + { + return $this->errno; + } + + function faultString() + { + return $this->errstr; + } + + function value() + { + return $this->val; + } + + function prepare_response() + { + $result = "\n"; + if ($this->errno) + { + $result .= ' + + + + faultCode + ' . $this->errno . ' + + + faultString + ' . $this->errstr . ' + + + +'; + } + else + { + $result .= "\n\n" . + $this->val->serialize_class() . + "\n"; + } + $result .= "\n"; + return $result; + } + + function decode($array=FALSE) + { + $CI =& get_instance(); + + if ($array !== FALSE && is_array($array)) + { + while (list($key) = each($array)) + { + if (is_array($array[$key])) + { + $array[$key] = $this->decode($array[$key]); + } + else + { + $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key]; + } + } + + $result = $array; + } + else + { + $result = $this->xmlrpc_decoder($this->val); + + if (is_array($result)) + { + $result = $this->decode($result); + } + else + { + $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result; + } + } + + return $result; + } + + + + //------------------------------------- + // XML-RPC Object to PHP Types + //------------------------------------- + + function xmlrpc_decoder($xmlrpc_val) + { + $kind = $xmlrpc_val->kindOf(); + + if ($kind == 'scalar') + { + return $xmlrpc_val->scalarval(); + } + elseif ($kind == 'array') + { + reset($xmlrpc_val->me); + list($a,$b) = each($xmlrpc_val->me); + $size = count($b); + + $arr = array(); + + for ($i = 0; $i < $size; $i++) + { + $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]); + } + return $arr; + } + elseif ($kind == 'struct') + { + reset($xmlrpc_val->me['struct']); + $arr = array(); + + while (list($key,$value) = each($xmlrpc_val->me['struct'])) + { + $arr[$key] = $this->xmlrpc_decoder($value); + } + return $arr; + } + } + + + //------------------------------------- + // ISO-8601 time to server or UTC time + //------------------------------------- + + function iso8601_decode($time, $utc=0) + { + // return a timet in the localtime, or UTC + $t = 0; + if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs)) + { + $fnc = ($utc == 1) ? 'gmmktime' : 'mktime'; + $t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } + return $t; + } + +} // End Response Class + + + +/** + * XML-RPC Message class + * + * @category XML-RPC + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html + */ +class XML_RPC_Message extends CI_Xmlrpc +{ + var $payload; + var $method_name; + var $params = array(); + var $xh = array(); + + public function __construct($method, $pars=0) + { + parent::__construct(); + + $this->method_name = $method; + if (is_array($pars) && count($pars) > 0) + { + for ($i=0; $iparams[] = $pars[$i]; + } + } + } + + //------------------------------------- + // Create Payload to Send + //------------------------------------- + + function createPayload() + { + $this->payload = "\r\n\r\n"; + $this->payload .= '' . $this->method_name . "\r\n"; + $this->payload .= "\r\n"; + + for ($i=0; $iparams); $i++) + { + // $p = XML_RPC_Values + $p = $this->params[$i]; + $this->payload .= "\r\n".$p->serialize_class()."\r\n"; + } + + $this->payload .= "\r\n\r\n"; + } + + //------------------------------------- + // Parse External XML-RPC Server's Response + //------------------------------------- + + function parseResponse($fp) + { + $data = ''; + + while ($datum = fread($fp, 4096)) + { + $data .= $datum; + } + + //------------------------------------- + // DISPLAY HTTP CONTENT for DEBUGGING + //------------------------------------- + + if ($this->debug === TRUE) + { + echo "
    ";
    +			echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
    +			echo "
    "; + } + + //------------------------------------- + // Check for data + //------------------------------------- + + if ($data == "") + { + error_log($this->xmlrpcstr['no_data']); + $r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']); + return $r; + } + + + //------------------------------------- + // Check for HTTP 200 Response + //------------------------------------- + + if (strncmp($data, 'HTTP', 4) == 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data)) + { + $errstr= substr($data, 0, strpos($data, "\n")-1); + $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']. ' (' . $errstr . ')'); + return $r; + } + + //------------------------------------- + // Create and Set Up XML Parser + //------------------------------------- + + $parser = xml_parser_create($this->xmlrpc_defencoding); + + $this->xh[$parser] = array(); + $this->xh[$parser]['isf'] = 0; + $this->xh[$parser]['ac'] = ''; + $this->xh[$parser]['headers'] = array(); + $this->xh[$parser]['stack'] = array(); + $this->xh[$parser]['valuestack'] = array(); + $this->xh[$parser]['isf_reason'] = 0; + + xml_set_object($parser, $this); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, 'open_tag', 'closing_tag'); + xml_set_character_data_handler($parser, 'character_data'); + //xml_set_default_handler($parser, 'default_handler'); + + + //------------------------------------- + // GET HEADERS + //------------------------------------- + + $lines = explode("\r\n", $data); + while (($line = array_shift($lines))) + { + if (strlen($line) < 1) + { + break; + } + $this->xh[$parser]['headers'][] = $line; + } + $data = implode("\r\n", $lines); + + + //------------------------------------- + // PARSE XML DATA + //------------------------------------- + + if ( ! xml_parse($parser, $data, count($data))) + { + $errstr = sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser)), + xml_get_current_line_number($parser)); + //error_log($errstr); + $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']); + xml_parser_free($parser); + return $r; + } + xml_parser_free($parser); + + // --------------------------------------- + // Got Ourselves Some Badness, It Seems + // --------------------------------------- + + if ($this->xh[$parser]['isf'] > 1) + { + if ($this->debug === TRUE) + { + echo "---Invalid Return---\n"; + echo $this->xh[$parser]['isf_reason']; + echo "---Invalid Return---\n\n"; + } + + $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']); + return $r; + } + elseif ( ! is_object($this->xh[$parser]['value'])) + { + $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']); + return $r; + } + + //------------------------------------- + // DISPLAY XML CONTENT for DEBUGGING + //------------------------------------- + + if ($this->debug === TRUE) + { + echo "
    ";
    +
    +			if (count($this->xh[$parser]['headers'] > 0))
    +			{
    +				echo "---HEADERS---\n";
    +				foreach ($this->xh[$parser]['headers'] as $header)
    +				{
    +					echo "$header\n";
    +				}
    +				echo "---END HEADERS---\n\n";
    +			}
    +
    +			echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
    +
    +			echo "---PARSED---\n" ;
    +			var_dump($this->xh[$parser]['value']);
    +			echo "\n---END PARSED---
    "; + } + + //------------------------------------- + // SEND RESPONSE + //------------------------------------- + + $v = $this->xh[$parser]['value']; + + if ($this->xh[$parser]['isf']) + { + $errno_v = $v->me['struct']['faultCode']; + $errstr_v = $v->me['struct']['faultString']; + $errno = $errno_v->scalarval(); + + if ($errno == 0) + { + // FAULT returned, errno needs to reflect that + $errno = -1; + } + + $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval()); + } + else + { + $r = new XML_RPC_Response($v); + } + + $r->headers = $this->xh[$parser]['headers']; + return $r; + } + + // ------------------------------------ + // Begin Return Message Parsing section + // ------------------------------------ + + // quick explanation of components: + // ac - used to accumulate values + // isf - used to indicate a fault + // lv - used to indicate "looking for a value": implements + // the logic to allow values with no types to be strings + // params - used to store parameters in method calls + // method - used to store method name + // stack - array with parent tree of the xml element, + // used to validate the nesting of elements + + //------------------------------------- + // Start Element Handler + //------------------------------------- + + function open_tag($the_parser, $name, $attrs) + { + // If invalid nesting, then return + if ($this->xh[$the_parser]['isf'] > 1) return; + + // Evaluate and check for correct nesting of XML elements + + if (count($this->xh[$the_parser]['stack']) == 0) + { + if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') + { + $this->xh[$the_parser]['isf'] = 2; + $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing'; + return; + } + } + else + { + // not top level element: see if parent is OK + if ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE)) + { + $this->xh[$the_parser]['isf'] = 2; + $this->xh[$the_parser]['isf_reason'] = "XML-RPC element $name cannot be child of ".$this->xh[$the_parser]['stack'][0]; + return; + } + } + + switch($name) + { + case 'STRUCT': + case 'ARRAY': + // Creates array for child elements + + $cur_val = array('value' => array(), + 'type' => $name); + + array_unshift($this->xh[$the_parser]['valuestack'], $cur_val); + break; + case 'METHODNAME': + case 'NAME': + $this->xh[$the_parser]['ac'] = ''; + break; + case 'FAULT': + $this->xh[$the_parser]['isf'] = 1; + break; + case 'PARAM': + $this->xh[$the_parser]['value'] = NULL; + break; + case 'VALUE': + $this->xh[$the_parser]['vt'] = 'value'; + $this->xh[$the_parser]['ac'] = ''; + $this->xh[$the_parser]['lv'] = 1; + break; + case 'I4': + case 'INT': + case 'STRING': + case 'BOOLEAN': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + if ($this->xh[$the_parser]['vt'] != 'value') + { + //two data elements inside a value: an error occurred! + $this->xh[$the_parser]['isf'] = 2; + $this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value"; + return; + } + + $this->xh[$the_parser]['ac'] = ''; + break; + case 'MEMBER': + // Set name of to nothing to prevent errors later if no is found + $this->xh[$the_parser]['valuestack'][0]['name'] = ''; + + // Set NULL value to check to see if value passed for this param/member + $this->xh[$the_parser]['value'] = NULL; + break; + case 'DATA': + case 'METHODCALL': + case 'METHODRESPONSE': + case 'PARAMS': + // valid elements that add little to processing + break; + default: + /// An Invalid Element is Found, so we have trouble + $this->xh[$the_parser]['isf'] = 2; + $this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name"; + break; + } + + // Add current element name to stack, to allow validation of nesting + array_unshift($this->xh[$the_parser]['stack'], $name); + + if ($name != 'VALUE') $this->xh[$the_parser]['lv'] = 0; + } + // END + + + //------------------------------------- + // End Element Handler + //------------------------------------- + + function closing_tag($the_parser, $name) + { + if ($this->xh[$the_parser]['isf'] > 1) return; + + // Remove current element from stack and set variable + // NOTE: If the XML validates, then we do not have to worry about + // the opening and closing of elements. Nesting is checked on the opening + // tag so we be safe there as well. + + $curr_elem = array_shift($this->xh[$the_parser]['stack']); + + switch($name) + { + case 'STRUCT': + case 'ARRAY': + $cur_val = array_shift($this->xh[$the_parser]['valuestack']); + $this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values']; + $this->xh[$the_parser]['vt'] = strtolower($name); + break; + case 'NAME': + $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac']; + break; + case 'BOOLEAN': + case 'I4': + case 'INT': + case 'STRING': + case 'DOUBLE': + case 'DATETIME.ISO8601': + case 'BASE64': + $this->xh[$the_parser]['vt'] = strtolower($name); + + if ($name == 'STRING') + { + $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; + } + elseif ($name=='DATETIME.ISO8601') + { + $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime; + $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; + } + elseif ($name=='BASE64') + { + $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']); + } + elseif ($name=='BOOLEAN') + { + // Translated BOOLEAN values to TRUE AND FALSE + if ($this->xh[$the_parser]['ac'] == '1') + { + $this->xh[$the_parser]['value'] = TRUE; + } + else + { + $this->xh[$the_parser]['value'] = FALSE; + } + } + elseif ($name=='DOUBLE') + { + // we have a DOUBLE + // we must check that only 0123456789-. are characters here + if ( ! preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])) + { + $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND'; + } + else + { + $this->xh[$the_parser]['value'] = (double)$this->xh[$the_parser]['ac']; + } + } + else + { + // we have an I4/INT + // we must check that only 0123456789- are characters here + if ( ! preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])) + { + $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND'; + } + else + { + $this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac']; + } + } + $this->xh[$the_parser]['ac'] = ''; + $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value + break; + case 'VALUE': + // This if() detects if no scalar was inside + if ($this->xh[$the_parser]['vt']=='value') + { + $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; + $this->xh[$the_parser]['vt'] = $this->xmlrpcString; + } + + // build the XML-RPC value out of the data received, and substitute it + $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']); + + if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY') + { + // Array + $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp; + } + else + { + // Struct + $this->xh[$the_parser]['value'] = $temp; + } + break; + case 'MEMBER': + $this->xh[$the_parser]['ac']=''; + + // If value add to array in the stack for the last element built + if ($this->xh[$the_parser]['value']) + { + $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value']; + } + break; + case 'DATA': + $this->xh[$the_parser]['ac']=''; + break; + case 'PARAM': + if ($this->xh[$the_parser]['value']) + { + $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value']; + } + break; + case 'METHODNAME': + $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']); + break; + case 'PARAMS': + case 'FAULT': + case 'METHODCALL': + case 'METHORESPONSE': + // We're all good kids with nuthin' to do + break; + default: + // End of an Invalid Element. Taken care of during the opening tag though + break; + } + } + + //------------------------------------- + // Parses Character Data + //------------------------------------- + + function character_data($the_parser, $data) + { + if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already + + // If a value has not been found + if ($this->xh[$the_parser]['lv'] != 3) + { + if ($this->xh[$the_parser]['lv'] == 1) + { + $this->xh[$the_parser]['lv'] = 2; // Found a value + } + + if ( ! @isset($this->xh[$the_parser]['ac'])) + { + $this->xh[$the_parser]['ac'] = ''; + } + + $this->xh[$the_parser]['ac'] .= $data; + } + } + + + function addParam($par) { $this->params[]=$par; } + + function output_parameters($array=FALSE) + { + $CI =& get_instance(); + + if ($array !== FALSE && is_array($array)) + { + while (list($key) = each($array)) + { + if (is_array($array[$key])) + { + $array[$key] = $this->output_parameters($array[$key]); + } + else + { + // 'bits' is for the MetaWeblog API image bits + // @todo - this needs to be made more general purpose + $array[$key] = ($key == 'bits' OR $this->xss_clean == FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]); + } + } + + $parameters = $array; + } + else + { + $parameters = array(); + + for ($i = 0; $i < count($this->params); $i++) + { + $a_param = $this->decode_message($this->params[$i]); + + if (is_array($a_param)) + { + $parameters[] = $this->output_parameters($a_param); + } + else + { + $parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param; + } + } + } + + return $parameters; + } + + + function decode_message($param) + { + $kind = $param->kindOf(); + + if ($kind == 'scalar') + { + return $param->scalarval(); + } + elseif ($kind == 'array') + { + reset($param->me); + list($a,$b) = each($param->me); + + $arr = array(); + + for($i = 0; $i < count($b); $i++) + { + $arr[] = $this->decode_message($param->me['array'][$i]); + } + + return $arr; + } + elseif ($kind == 'struct') + { + reset($param->me['struct']); + + $arr = array(); + + while (list($key,$value) = each($param->me['struct'])) + { + $arr[$key] = $this->decode_message($value); + } + + return $arr; + } + } + +} // End XML_RPC_Messages class + + + +/** + * XML-RPC Values class + * + * @category XML-RPC + * @author ExpressionEngine Dev Team + * @link http://codeigniter.com/user_guide/libraries/xmlrpc.html + */ +class XML_RPC_Values extends CI_Xmlrpc +{ + var $me = array(); + var $mytype = 0; + + public function __construct($val=-1, $type='') + { + parent::__construct(); + + if ($val != -1 OR $type != '') + { + $type = $type == '' ? 'string' : $type; + + if ($this->xmlrpcTypes[$type] == 1) + { + $this->addScalar($val,$type); + } + elseif ($this->xmlrpcTypes[$type] == 2) + { + $this->addArray($val); + } + elseif ($this->xmlrpcTypes[$type] == 3) + { + $this->addStruct($val); + } + } + } + + function addScalar($val, $type='string') + { + $typeof = $this->xmlrpcTypes[$type]; + + if ($this->mytype==1) + { + echo 'XML_RPC_Values: scalar can have only one value
    '; + return 0; + } + + if ($typeof != 1) + { + echo 'XML_RPC_Values: not a scalar type (${typeof})
    '; + return 0; + } + + if ($type == $this->xmlrpcBoolean) + { + if (strcasecmp($val,'true')==0 OR $val==1 OR ($val==true && strcasecmp($val,'false'))) + { + $val = 1; + } + else + { + $val=0; + } + } + + if ($this->mytype == 2) + { + // adding to an array here + $ar = $this->me['array']; + $ar[] = new XML_RPC_Values($val, $type); + $this->me['array'] = $ar; + } + else + { + // a scalar, so set the value and remember we're scalar + $this->me[$type] = $val; + $this->mytype = $typeof; + } + return 1; + } + + function addArray($vals) + { + if ($this->mytype != 0) + { + echo 'XML_RPC_Values: already initialized as a [' . $this->kindOf() . ']
    '; + return 0; + } + + $this->mytype = $this->xmlrpcTypes['array']; + $this->me['array'] = $vals; + return 1; + } + + function addStruct($vals) + { + if ($this->mytype != 0) + { + echo 'XML_RPC_Values: already initialized as a [' . $this->kindOf() . ']
    '; + return 0; + } + $this->mytype = $this->xmlrpcTypes['struct']; + $this->me['struct'] = $vals; + return 1; + } + + function kindOf() + { + switch($this->mytype) + { + case 3: + return 'struct'; + break; + case 2: + return 'array'; + break; + case 1: + return 'scalar'; + break; + default: + return 'undef'; + } + } + + function serializedata($typ, $val) + { + $rs = ''; + + switch($this->xmlrpcTypes[$typ]) + { + case 3: + // struct + $rs .= "\n"; + reset($val); + while (list($key2, $val2) = each($val)) + { + $rs .= "\n{$key2}\n"; + $rs .= $this->serializeval($val2); + $rs .= "\n"; + } + $rs .= ''; + break; + case 2: + // array + $rs .= "\n\n"; + for($i=0; $i < count($val); $i++) + { + $rs .= $this->serializeval($val[$i]); + } + $rs.="\n\n"; + break; + case 1: + // others + switch ($typ) + { + case $this->xmlrpcBase64: + $rs .= "<{$typ}>" . base64_encode((string)$val) . "\n"; + break; + case $this->xmlrpcBoolean: + $rs .= "<{$typ}>" . ((bool)$val ? '1' : '0') . "\n"; + break; + case $this->xmlrpcString: + $rs .= "<{$typ}>" . htmlspecialchars((string)$val). "\n"; + break; + default: + $rs .= "<{$typ}>{$val}\n"; + break; + } + default: + break; + } + return $rs; + } + + function serialize_class() + { + return $this->serializeval($this); + } + + function serializeval($o) + { + $ar = $o->me; + reset($ar); + + list($typ, $val) = each($ar); + $rs = "\n".$this->serializedata($typ, $val)."\n"; + return $rs; + } + + function scalarval() + { + reset($this->me); + list($a,$b) = each($this->me); + return $b; + } + + + //------------------------------------- + // Encode time in ISO-8601 form. + //------------------------------------- + + // Useful for sending time in XML-RPC + + function iso8601_encode($time, $utc=0) + { + if ($utc == 1) + { + $t = strftime("%Y%m%dT%H:%i:%s", $time); + } + else + { + if (function_exists('gmstrftime')) + $t = gmstrftime("%Y%m%dT%H:%i:%s", $time); + else + $t = strftime("%Y%m%dT%H:%i:%s", $time - date('Z')); + } + return $t; + } + +} +// END XML_RPC_Values Class + +/* End of file Xmlrpc.php */ +/* Location: ./system/libraries/Xmlrpc.php */ \ No newline at end of file diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php new file mode 100644 index 0000000..9cd3321 --- /dev/null +++ b/system/libraries/Xmlrpcs.php @@ -0,0 +1,612 @@ +set_system_methods(); + + if (isset($config['functions']) && is_array($config['functions'])) + { + $this->methods = array_merge($this->methods, $config['functions']); + } + + log_message('debug', "XML-RPC Server Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Initialize Prefs and Serve + * + * @access public + * @param mixed + * @return void + */ + function initialize($config=array()) + { + if (isset($config['functions']) && is_array($config['functions'])) + { + $this->methods = array_merge($this->methods, $config['functions']); + } + + if (isset($config['debug'])) + { + $this->debug = $config['debug']; + } + + if (isset($config['object']) && is_object($config['object'])) + { + $this->object = $config['object']; + } + + if (isset($config['xss_clean'])) + { + $this->xss_clean = $config['xss_clean']; + } + } + + // -------------------------------------------------------------------- + + /** + * Setting of System Methods + * + * @access public + * @return void + */ + function set_system_methods() + { + $this->methods = array( + 'system.listMethods' => array( + 'function' => 'this.listMethods', + 'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString), array($this->xmlrpcArray)), + 'docstring' => 'Returns an array of available methods on this server'), + 'system.methodHelp' => array( + 'function' => 'this.methodHelp', + 'signature' => array(array($this->xmlrpcString, $this->xmlrpcString)), + 'docstring' => 'Returns a documentation string for the specified method'), + 'system.methodSignature' => array( + 'function' => 'this.methodSignature', + 'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString)), + 'docstring' => 'Returns an array describing the return type and required parameters of a method'), + 'system.multicall' => array( + 'function' => 'this.multicall', + 'signature' => array(array($this->xmlrpcArray, $this->xmlrpcArray)), + 'docstring' => 'Combine multiple RPC calls in one request. See http://www.xmlrpc.com/discuss/msgReader$1208 for details') + ); + } + + // -------------------------------------------------------------------- + + /** + * Main Server Function + * + * @access public + * @return void + */ + function serve() + { + $r = $this->parseRequest(); + $payload = 'xmlrpc_defencoding.'"?'.'>'."\n"; + $payload .= $this->debug_msg; + $payload .= $r->prepare_response(); + + header("Content-Type: text/xml"); + header("Content-Length: ".strlen($payload)); + exit($payload); + } + + // -------------------------------------------------------------------- + + /** + * Add Method to Class + * + * @access public + * @param string method name + * @param string function + * @param string signature + * @param string docstring + * @return void + */ + function add_to_map($methodname, $function, $sig, $doc) + { + $this->methods[$methodname] = array( + 'function' => $function, + 'signature' => $sig, + 'docstring' => $doc + ); + } + + // -------------------------------------------------------------------- + + /** + * Parse Server Request + * + * @access public + * @param string data + * @return object xmlrpc response + */ + function parseRequest($data='') + { + global $HTTP_RAW_POST_DATA; + + //------------------------------------- + // Get Data + //------------------------------------- + + if ($data == '') + { + $data = $HTTP_RAW_POST_DATA; + } + + //------------------------------------- + // Set up XML Parser + //------------------------------------- + + $parser = xml_parser_create($this->xmlrpc_defencoding); + $parser_object = new XML_RPC_Message("filler"); + + $parser_object->xh[$parser] = array(); + $parser_object->xh[$parser]['isf'] = 0; + $parser_object->xh[$parser]['isf_reason'] = ''; + $parser_object->xh[$parser]['params'] = array(); + $parser_object->xh[$parser]['stack'] = array(); + $parser_object->xh[$parser]['valuestack'] = array(); + $parser_object->xh[$parser]['method'] = ''; + + xml_set_object($parser, $parser_object); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, 'open_tag', 'closing_tag'); + xml_set_character_data_handler($parser, 'character_data'); + //xml_set_default_handler($parser, 'default_handler'); + + + //------------------------------------- + // PARSE + PROCESS XML DATA + //------------------------------------- + + if ( ! xml_parse($parser, $data, 1)) + { + // return XML error as a faultCode + $r = new XML_RPC_Response(0, + $this->xmlrpcerrxml + xml_get_error_code($parser), + sprintf('XML error: %s at line %d', + xml_error_string(xml_get_error_code($parser)), + xml_get_current_line_number($parser))); + xml_parser_free($parser); + } + elseif ($parser_object->xh[$parser]['isf']) + { + return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']); + } + else + { + xml_parser_free($parser); + + $m = new XML_RPC_Message($parser_object->xh[$parser]['method']); + $plist=''; + + for ($i=0; $i < count($parser_object->xh[$parser]['params']); $i++) + { + if ($this->debug === TRUE) + { + $plist .= "$i - " . print_r(get_object_vars($parser_object->xh[$parser]['params'][$i]), TRUE). ";\n"; + } + + $m->addParam($parser_object->xh[$parser]['params'][$i]); + } + + if ($this->debug === TRUE) + { + echo "
    ";
    +				echo "---PLIST---\n" . $plist . "\n---PLIST END---\n\n";
    +				echo "
    "; + } + + $r = $this->_execute($m); + } + + //------------------------------------- + // SET DEBUGGING MESSAGE + //------------------------------------- + + if ($this->debug === TRUE) + { + $this->debug_msg = "\n"; + } + + return $r; + } + + // -------------------------------------------------------------------- + + /** + * Executes the Method + * + * @access protected + * @param object + * @return mixed + */ + function _execute($m) + { + $methName = $m->method_name; + + // Check to see if it is a system call + $system_call = (strncmp($methName, 'system', 5) == 0) ? TRUE : FALSE; + + if ($this->xss_clean == FALSE) + { + $m->xss_clean = FALSE; + } + + //------------------------------------- + // Valid Method + //------------------------------------- + + if ( ! isset($this->methods[$methName]['function'])) + { + return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']); + } + + //------------------------------------- + // Check for Method (and Object) + //------------------------------------- + + $method_parts = explode(".", $this->methods[$methName]['function']); + $objectCall = (isset($method_parts['1']) && $method_parts['1'] != "") ? TRUE : FALSE; + + if ($system_call === TRUE) + { + if ( ! is_callable(array($this,$method_parts['1']))) + { + return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']); + } + } + else + { + if ($objectCall && ! is_callable(array($method_parts['0'],$method_parts['1']))) + { + return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']); + } + elseif ( ! $objectCall && ! is_callable($this->methods[$methName]['function'])) + { + return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']); + } + } + + //------------------------------------- + // Checking Methods Signature + //------------------------------------- + + if (isset($this->methods[$methName]['signature'])) + { + $sig = $this->methods[$methName]['signature']; + for ($i=0; $iparams)+1) + { + for ($n=0; $n < count($m->params); $n++) + { + $p = $m->params[$n]; + $pt = ($p->kindOf() == 'scalar') ? $p->scalarval() : $p->kindOf(); + + if ($pt != $current_sig[$n+1]) + { + $pno = $n+1; + $wanted = $current_sig[$n+1]; + + return new XML_RPC_Response(0, + $this->xmlrpcerr['incorrect_params'], + $this->xmlrpcstr['incorrect_params'] . + ": Wanted {$wanted}, got {$pt} at param {$pno})"); + } + } + } + } + } + + //------------------------------------- + // Calls the Function + //------------------------------------- + + if ($objectCall === TRUE) + { + if ($method_parts[0] == "this" && $system_call == TRUE) + { + return call_user_func(array($this, $method_parts[1]), $m); + } + else + { + if ($this->object === FALSE) + { + $CI =& get_instance(); + return $CI->$method_parts['1']($m); + } + else + { + return $this->object->$method_parts['1']($m); + //return call_user_func(array(&$method_parts['0'],$method_parts['1']), $m); + } + } + } + else + { + return call_user_func($this->methods[$methName]['function'], $m); + } + } + + // -------------------------------------------------------------------- + + /** + * Server Function: List Methods + * + * @access public + * @param mixed + * @return object + */ + function listMethods($m) + { + $v = new XML_RPC_Values(); + $output = array(); + + foreach ($this->methods as $key => $value) + { + $output[] = new XML_RPC_Values($key, 'string'); + } + + foreach ($this->system_methods as $key => $value) + { + $output[]= new XML_RPC_Values($key, 'string'); + } + + $v->addArray($output); + return new XML_RPC_Response($v); + } + + // -------------------------------------------------------------------- + + /** + * Server Function: Return Signature for Method + * + * @access public + * @param mixed + * @return object + */ + function methodSignature($m) + { + $parameters = $m->output_parameters(); + $method_name = $parameters[0]; + + if (isset($this->methods[$method_name])) + { + if ($this->methods[$method_name]['signature']) + { + $sigs = array(); + $signature = $this->methods[$method_name]['signature']; + + for ($i=0; $i < count($signature); $i++) + { + $cursig = array(); + $inSig = $signature[$i]; + for ($j=0; $jxmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']); + } + return $r; + } + + // -------------------------------------------------------------------- + + /** + * Server Function: Doc String for Method + * + * @access public + * @param mixed + * @return object + */ + function methodHelp($m) + { + $parameters = $m->output_parameters(); + $method_name = $parameters[0]; + + if (isset($this->methods[$method_name])) + { + $docstring = isset($this->methods[$method_name]['docstring']) ? $this->methods[$method_name]['docstring'] : ''; + + return new XML_RPC_Response(new XML_RPC_Values($docstring, 'string')); + } + else + { + return new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']); + } + } + + // -------------------------------------------------------------------- + + /** + * Server Function: Multi-call + * + * @access public + * @param mixed + * @return object + */ + function multicall($m) + { + // Disabled + return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']); + + $parameters = $m->output_parameters(); + $calls = $parameters[0]; + + $result = array(); + + foreach ($calls as $value) + { + //$attempt = $this->_execute(new XML_RPC_Message($value[0], $value[1])); + + $m = new XML_RPC_Message($value[0]); + $plist=''; + + for ($i=0; $i < count($value[1]); $i++) + { + $m->addParam(new XML_RPC_Values($value[1][$i], 'string')); + } + + $attempt = $this->_execute($m); + + if ($attempt->faultCode() != 0) + { + return $attempt; + } + + $result[] = new XML_RPC_Values(array($attempt->value()), 'array'); + } + + return new XML_RPC_Response(new XML_RPC_Values($result, 'array')); + } + + // -------------------------------------------------------------------- + + /** + * Multi-call Function: Error Handling + * + * @access public + * @param mixed + * @return object + */ + function multicall_error($err) + { + $str = is_string($err) ? $this->xmlrpcstr["multicall_${err}"] : $err->faultString(); + $code = is_string($err) ? $this->xmlrpcerr["multicall_${err}"] : $err->faultCode(); + + $struct['faultCode'] = new XML_RPC_Values($code, 'int'); + $struct['faultString'] = new XML_RPC_Values($str, 'string'); + + return new XML_RPC_Values($struct, 'struct'); + } + + // -------------------------------------------------------------------- + + /** + * Multi-call Function: Processes method + * + * @access public + * @param mixed + * @return object + */ + function do_multicall($call) + { + if ($call->kindOf() != 'struct') + { + return $this->multicall_error('notstruct'); + } + elseif ( ! $methName = $call->me['struct']['methodName']) + { + return $this->multicall_error('nomethod'); + } + + list($scalar_type,$scalar_value)=each($methName->me); + $scalar_type = $scalar_type == $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type; + + if ($methName->kindOf() != 'scalar' OR $scalar_type != 'string') + { + return $this->multicall_error('notstring'); + } + elseif ($scalar_value == 'system.multicall') + { + return $this->multicall_error('recursion'); + } + elseif ( ! $params = $call->me['struct']['params']) + { + return $this->multicall_error('noparams'); + } + elseif ($params->kindOf() != 'array') + { + return $this->multicall_error('notarray'); + } + + list($a,$b)=each($params->me); + $numParams = count($b); + + $msg = new XML_RPC_Message($scalar_value); + for ($i = 0; $i < $numParams; $i++) + { + $msg->params[] = $params->me['array'][$i]; + } + + $result = $this->_execute($msg); + + if ($result->faultCode() != 0) + { + return $this->multicall_error($result); + } + + return new XML_RPC_Values(array($result->value()), 'array'); + } + +} +// END XML_RPC_Server class + + +/* End of file Xmlrpcs.php */ +/* Location: ./system/libraries/Xmlrpcs.php */ \ No newline at end of file diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php new file mode 100644 index 0000000..666327d --- /dev/null +++ b/system/libraries/Zip.php @@ -0,0 +1,423 @@ +now = time(); + } + + // -------------------------------------------------------------------- + + /** + * Add Directory + * + * Lets you add a virtual directory into which you can place files. + * + * @access public + * @param mixed the directory name. Can be string or array + * @return void + */ + function add_dir($directory) + { + foreach ((array)$directory as $dir) + { + if ( ! preg_match("|.+/$|", $dir)) + { + $dir .= '/'; + } + + $dir_time = $this->_get_mod_time($dir); + + $this->_add_dir($dir, $dir_time['file_mtime'], $dir_time['file_mdate']); + } + } + + // -------------------------------------------------------------------- + + /** + * Get file/directory modification time + * + * If this is a newly created file/dir, we will set the time to 'now' + * + * @param string path to file + * @return array filemtime/filemdate + */ + function _get_mod_time($dir) + { + // filemtime() will return false, but it does raise an error. + $date = (@filemtime($dir)) ? filemtime($dir) : getdate($this->now); + + $time['file_mtime'] = ($date['hours'] << 11) + ($date['minutes'] << 5) + $date['seconds'] / 2; + $time['file_mdate'] = (($date['year'] - 1980) << 9) + ($date['mon'] << 5) + $date['mday']; + + return $time; + } + + // -------------------------------------------------------------------- + + /** + * Add Directory + * + * @access private + * @param string the directory name + * @return void + */ + function _add_dir($dir, $file_mtime, $file_mdate) + { + $dir = str_replace("\\", "/", $dir); + + $this->zipdata .= + "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00" + .pack('v', $file_mtime) + .pack('v', $file_mdate) + .pack('V', 0) // crc32 + .pack('V', 0) // compressed filesize + .pack('V', 0) // uncompressed filesize + .pack('v', strlen($dir)) // length of pathname + .pack('v', 0) // extra field length + .$dir + // below is "data descriptor" segment + .pack('V', 0) // crc32 + .pack('V', 0) // compressed filesize + .pack('V', 0); // uncompressed filesize + + $this->directory .= + "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00" + .pack('v', $file_mtime) + .pack('v', $file_mdate) + .pack('V',0) // crc32 + .pack('V',0) // compressed filesize + .pack('V',0) // uncompressed filesize + .pack('v', strlen($dir)) // length of pathname + .pack('v', 0) // extra field length + .pack('v', 0) // file comment length + .pack('v', 0) // disk number start + .pack('v', 0) // internal file attributes + .pack('V', 16) // external file attributes - 'directory' bit set + .pack('V', $this->offset) // relative offset of local header + .$dir; + + $this->offset = strlen($this->zipdata); + $this->entries++; + } + + // -------------------------------------------------------------------- + + /** + * Add Data to Zip + * + * Lets you add files to the archive. If the path is included + * in the filename it will be placed within a directory. Make + * sure you use add_dir() first to create the folder. + * + * @access public + * @param mixed + * @param string + * @return void + */ + function add_data($filepath, $data = NULL) + { + if (is_array($filepath)) + { + foreach ($filepath as $path => $data) + { + $file_data = $this->_get_mod_time($path); + + $this->_add_data($path, $data, $file_data['file_mtime'], $file_data['file_mdate']); + } + } + else + { + $file_data = $this->_get_mod_time($filepath); + + $this->_add_data($filepath, $data, $file_data['file_mtime'], $file_data['file_mdate']); + } + } + + // -------------------------------------------------------------------- + + /** + * Add Data to Zip + * + * @access private + * @param string the file name/path + * @param string the data to be encoded + * @return void + */ + function _add_data($filepath, $data, $file_mtime, $file_mdate) + { + $filepath = str_replace("\\", "/", $filepath); + + $uncompressed_size = strlen($data); + $crc32 = crc32($data); + + $gzdata = gzcompress($data); + $gzdata = substr($gzdata, 2, -4); + $compressed_size = strlen($gzdata); + + $this->zipdata .= + "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00" + .pack('v', $file_mtime) + .pack('v', $file_mdate) + .pack('V', $crc32) + .pack('V', $compressed_size) + .pack('V', $uncompressed_size) + .pack('v', strlen($filepath)) // length of filename + .pack('v', 0) // extra field length + .$filepath + .$gzdata; // "file data" segment + + $this->directory .= + "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00" + .pack('v', $file_mtime) + .pack('v', $file_mdate) + .pack('V', $crc32) + .pack('V', $compressed_size) + .pack('V', $uncompressed_size) + .pack('v', strlen($filepath)) // length of filename + .pack('v', 0) // extra field length + .pack('v', 0) // file comment length + .pack('v', 0) // disk number start + .pack('v', 0) // internal file attributes + .pack('V', 32) // external file attributes - 'archive' bit set + .pack('V', $this->offset) // relative offset of local header + .$filepath; + + $this->offset = strlen($this->zipdata); + $this->entries++; + $this->file_num++; + } + + // -------------------------------------------------------------------- + + /** + * Read the contents of a file and add it to the zip + * + * @access public + * @return bool + */ + function read_file($path, $preserve_filepath = FALSE) + { + if ( ! file_exists($path)) + { + return FALSE; + } + + if (FALSE !== ($data = file_get_contents($path))) + { + $name = str_replace("\\", "/", $path); + + if ($preserve_filepath === FALSE) + { + $name = preg_replace("|.*/(.+)|", "\\1", $name); + } + + $this->add_data($name, $data); + return TRUE; + } + return FALSE; + } + + // ------------------------------------------------------------------------ + + /** + * Read a directory and add it to the zip. + * + * This function recursively reads a folder and everything it contains (including + * sub-folders) and creates a zip based on it. Whatever directory structure + * is in the original file path will be recreated in the zip file. + * + * @access public + * @param string path to source + * @return bool + */ + function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL) + { + if ( ! $fp = @opendir($path)) + { + return FALSE; + } + + // Set the original directory root for child dir's to use as relative + if ($root_path === NULL) + { + $root_path = dirname($path).'/'; + } + + while (FALSE !== ($file = readdir($fp))) + { + if (substr($file, 0, 1) == '.') + { + continue; + } + + if (@is_dir($path.$file)) + { + $this->read_dir($path.$file."/", $preserve_filepath, $root_path); + } + else + { + if (FALSE !== ($data = file_get_contents($path.$file))) + { + $name = str_replace("\\", "/", $path); + + if ($preserve_filepath === FALSE) + { + $name = str_replace($root_path, '', $name); + } + + $this->add_data($name.$file, $data); + } + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Get the Zip file + * + * @access public + * @return binary string + */ + function get_zip() + { + // Is there any data to return? + if ($this->entries == 0) + { + return FALSE; + } + + $zip_data = $this->zipdata; + $zip_data .= $this->directory."\x50\x4b\x05\x06\x00\x00\x00\x00"; + $zip_data .= pack('v', $this->entries); // total # of entries "on this disk" + $zip_data .= pack('v', $this->entries); // total # of entries overall + $zip_data .= pack('V', strlen($this->directory)); // size of central dir + $zip_data .= pack('V', strlen($this->zipdata)); // offset to start of central dir + $zip_data .= "\x00\x00"; // .zip file comment length + + return $zip_data; + } + + // -------------------------------------------------------------------- + + /** + * Write File to the specified directory + * + * Lets you write a file + * + * @access public + * @param string the file name + * @return bool + */ + function archive($filepath) + { + if ( ! ($fp = @fopen($filepath, FOPEN_WRITE_CREATE_DESTRUCTIVE))) + { + return FALSE; + } + + flock($fp, LOCK_EX); + fwrite($fp, $this->get_zip()); + flock($fp, LOCK_UN); + fclose($fp); + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Download + * + * @access public + * @param string the file name + * @param string the data to be encoded + * @return bool + */ + function download($filename = 'backup.zip') + { + if ( ! preg_match("|.+?\.zip$|", $filename)) + { + $filename .= '.zip'; + } + + $CI =& get_instance(); + $CI->load->helper('download'); + + $get_zip = $this->get_zip(); + + $zip_content =& $get_zip; + + force_download($filename, $zip_content); + } + + // -------------------------------------------------------------------- + + /** + * Initialize Data + * + * Lets you clear current zip data. Useful if you need to create + * multiple zips with different data. + * + * @access public + * @return void + */ + function clear_data() + { + $this->zipdata = ''; + $this->directory = ''; + $this->entries = 0; + $this->file_num = 0; + $this->offset = 0; + } + +} + +/* End of file Zip.php */ +/* Location: ./system/libraries/Zip.php */ \ No newline at end of file diff --git a/system/libraries/index.html b/system/libraries/index.html new file mode 100644 index 0000000..c942a79 --- /dev/null +++ b/system/libraries/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

    Directory access is forbidden.

    + + + \ No newline at end of file diff --git a/system/libraries/javascript/Jquery.php b/system/libraries/javascript/Jquery.php new file mode 100644 index 0000000..baab83d --- /dev/null +++ b/system/libraries/javascript/Jquery.php @@ -0,0 +1,1071 @@ +CI =& get_instance(); + extract($params); + + if ($autoload === TRUE) + { + $this->script(); + } + + log_message('debug', "Jquery Class Initialized"); + } + + // -------------------------------------------------------------------- + // Event Code + // -------------------------------------------------------------------- + + /** + * Blur + * + * Outputs a jQuery blur event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _blur($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'blur'); + } + + // -------------------------------------------------------------------- + + /** + * Change + * + * Outputs a jQuery change event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _change($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'change'); + } + + // -------------------------------------------------------------------- + + /** + * Click + * + * Outputs a jQuery click event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @param boolean whether or not to return false + * @return string + */ + function _click($element = 'this', $js = '', $ret_false = TRUE) + { + if ( ! is_array($js)) + { + $js = array($js); + } + + if ($ret_false) + { + $js[] = "return false;"; + } + + return $this->_add_event($element, $js, 'click'); + } + + // -------------------------------------------------------------------- + + /** + * Double Click + * + * Outputs a jQuery dblclick event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _dblclick($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'dblclick'); + } + + // -------------------------------------------------------------------- + + /** + * Error + * + * Outputs a jQuery error event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _error($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'error'); + } + + // -------------------------------------------------------------------- + + /** + * Focus + * + * Outputs a jQuery focus event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _focus($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'focus'); + } + + // -------------------------------------------------------------------- + + /** + * Hover + * + * Outputs a jQuery hover event + * + * @access private + * @param string - element + * @param string - Javascript code for mouse over + * @param string - Javascript code for mouse out + * @return string + */ + function _hover($element = 'this', $over, $out) + { + $event = "\n\t$(" . $this->_prep_element($element) . ").hover(\n\t\tfunction()\n\t\t{\n\t\t\t{$over}\n\t\t}, \n\t\tfunction()\n\t\t{\n\t\t\t{$out}\n\t\t});\n"; + + $this->jquery_code_for_compile[] = $event; + + return $event; + } + + // -------------------------------------------------------------------- + + /** + * Keydown + * + * Outputs a jQuery keydown event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _keydown($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'keydown'); + } + + // -------------------------------------------------------------------- + + /** + * Keyup + * + * Outputs a jQuery keydown event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _keyup($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'keyup'); + } + + // -------------------------------------------------------------------- + + /** + * Load + * + * Outputs a jQuery load event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _load($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'load'); + } + + // -------------------------------------------------------------------- + + /** + * Mousedown + * + * Outputs a jQuery mousedown event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _mousedown($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mousedown'); + } + + // -------------------------------------------------------------------- + + /** + * Mouse Out + * + * Outputs a jQuery mouseout event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _mouseout($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mouseout'); + } + + // -------------------------------------------------------------------- + + /** + * Mouse Over + * + * Outputs a jQuery mouseover event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _mouseover($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mouseover'); + } + + // -------------------------------------------------------------------- + + /** + * Mouseup + * + * Outputs a jQuery mouseup event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _mouseup($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mouseup'); + } + + // -------------------------------------------------------------------- + + /** + * Output + * + * Outputs script directly + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _output($array_js = '') + { + if ( ! is_array($array_js)) + { + $array_js = array($array_js); + } + + foreach ($array_js as $js) + { + $this->jquery_code_for_compile[] = "\t$js\n"; + } + } + + // -------------------------------------------------------------------- + + /** + * Resize + * + * Outputs a jQuery resize event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _resize($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'resize'); + } + + // -------------------------------------------------------------------- + + /** + * Scroll + * + * Outputs a jQuery scroll event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _scroll($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'scroll'); + } + + // -------------------------------------------------------------------- + + /** + * Unload + * + * Outputs a jQuery unload event + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + function _unload($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'unload'); + } + + // -------------------------------------------------------------------- + // Effects + // -------------------------------------------------------------------- + + /** + * Add Class + * + * Outputs a jQuery addClass event + * + * @access private + * @param string - element + * @return string + */ + function _addClass($element = 'this', $class='') + { + $element = $this->_prep_element($element); + $str = "$({$element}).addClass(\"$class\");"; + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Animate + * + * Outputs a jQuery animate event + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _animate($element = 'this', $params = array(), $speed = '', $extra = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + $animations = "\t\t\t"; + + foreach ($params as $param=>$value) + { + $animations .= $param.': \''.$value.'\', '; + } + + $animations = substr($animations, 0, -2); // remove the last ", " + + if ($speed != '') + { + $speed = ', '.$speed; + } + + if ($extra != '') + { + $extra = ', '.$extra; + } + + $str = "$({$element}).animate({\n$animations\n\t\t}".$speed.$extra.");"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Fade In + * + * Outputs a jQuery hide event + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _fadeIn($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).fadeIn({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Fade Out + * + * Outputs a jQuery hide event + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _fadeOut($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).fadeOut({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Hide + * + * Outputs a jQuery hide action + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _hide($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).hide({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Remove Class + * + * Outputs a jQuery remove class event + * + * @access private + * @param string - element + * @return string + */ + function _removeClass($element = 'this', $class='') + { + $element = $this->_prep_element($element); + $str = "$({$element}).removeClass(\"$class\");"; + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Slide Up + * + * Outputs a jQuery slideUp event + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _slideUp($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).slideUp({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Slide Down + * + * Outputs a jQuery slideDown event + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _slideDown($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).slideDown({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Slide Toggle + * + * Outputs a jQuery slideToggle event + * + * @access public + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _slideToggle($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).slideToggle({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Toggle + * + * Outputs a jQuery toggle event + * + * @access private + * @param string - element + * @return string + */ + function _toggle($element = 'this') + { + $element = $this->_prep_element($element); + $str = "$({$element}).toggle();"; + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Toggle Class + * + * Outputs a jQuery toggle class event + * + * @access private + * @param string - element + * @return string + */ + function _toggleClass($element = 'this', $class='') + { + $element = $this->_prep_element($element); + $str = "$({$element}).toggleClass(\"$class\");"; + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Show + * + * Outputs a jQuery show event + * + * @access private + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + function _show($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback != '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + $str = "$({$element}).show({$speed}{$callback});"; + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Updater + * + * An Ajax call that populates the designated DOM node with + * returned content + * + * @access private + * @param string The element to attach the event to + * @param string the controller to run the call against + * @param string optional parameters + * @return string + */ + + function _updater($container = 'this', $controller, $options = '') + { + $container = $this->_prep_element($container); + + $controller = (strpos('://', $controller) === FALSE) ? $controller : $this->CI->config->site_url($controller); + + // ajaxStart and ajaxStop are better choices here... but this is a stop gap + if ($this->CI->config->item('javascript_ajax_img') == '') + { + $loading_notifier = "Loading..."; + } + else + { + $loading_notifier = 'CI->config->slash_item('base_url') . $this->CI->config->item('javascript_ajax_img') . '\' alt=\'Loading\' />'; + } + + $updater = "$($container).empty();\n"; // anything that was in... get it out + $updater .= "\t\t$($container).prepend(\"$loading_notifier\");\n"; // to replace with an image + + $request_options = ''; + if ($options != '') + { + $request_options .= ", {"; + $request_options .= (is_array($options)) ? "'".implode("', '", $options)."'" : "'".str_replace(":", "':'", $options)."'"; + $request_options .= "}"; + } + + $updater .= "\t\t$($container).load('$controller'$request_options);"; + return $updater; + } + + + // -------------------------------------------------------------------- + // Pre-written handy stuff + // -------------------------------------------------------------------- + + /** + * Zebra tables + * + * @access private + * @param string table name + * @param string plugin location + * @return string + */ + function _zebraTables($class = '', $odd = 'odd', $hover = '') + { + $class = ($class != '') ? '.'.$class : ''; + + $zebra = "\t\$(\"table{$class} tbody tr:nth-child(even)\").addClass(\"{$odd}\");"; + + $this->jquery_code_for_compile[] = $zebra; + + if ($hover != '') + { + $hover = $this->hover("table{$class} tbody tr", "$(this).addClass('hover');", "$(this).removeClass('hover');"); + } + + return $zebra; + } + + + + // -------------------------------------------------------------------- + // Plugins + // -------------------------------------------------------------------- + + /** + * Corner Plugin + * + * http://www.malsup.com/jquery/corner/ + * + * @access public + * @param string target + * @return string + */ + function corner($element = '', $corner_style = '') + { + // may want to make this configurable down the road + $corner_location = '/plugins/jquery.corner.js'; + + if ($corner_style != '') + { + $corner_style = '"'.$corner_style.'"'; + } + + return "$(" . $this->_prep_element($element) . ").corner(".$corner_style.");"; + } + + // -------------------------------------------------------------------- + + /** + * modal window + * + * Load a thickbox modal window + * + * @access public + * @return void + */ + function modal($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * Effect + * + * Load an Effect library + * + * @access public + * @return void + */ + function effect($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * Plugin + * + * Load a plugin library + * + * @access public + * @return void + */ + function plugin($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * UI + * + * Load a user interface library + * + * @access public + * @return void + */ + function ui($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + // -------------------------------------------------------------------- + + /** + * Sortable + * + * Creates a jQuery sortable + * + * @access public + * @return void + */ + function sortable($element, $options = array()) + { + + if (count($options) > 0) + { + $sort_options = array(); + foreach ($options as $k=>$v) + { + $sort_options[] = "\n\t\t".$k.': '.$v.""; + } + $sort_options = implode(",", $sort_options); + } + else + { + $sort_options = ''; + } + + return "$(" . $this->_prep_element($element) . ").sortable({".$sort_options."\n\t});"; + } + + // -------------------------------------------------------------------- + + /** + * Table Sorter Plugin + * + * @access public + * @param string table name + * @param string plugin location + * @return string + */ + function tablesorter($table = '', $options = '') + { + $this->jquery_code_for_compile[] = "\t$(" . $this->_prep_element($table) . ").tablesorter($options);\n"; + } + + // -------------------------------------------------------------------- + // Class functions + // -------------------------------------------------------------------- + + /** + * Add Event + * + * Constructs the syntax for an event, and adds to into the array for compilation + * + * @access private + * @param string The element to attach the event to + * @param string The code to execute + * @param string The event to pass + * @return string + */ + function _add_event($element, $js, $event) + { + if (is_array($js)) + { + $js = implode("\n\t\t", $js); + + } + + $event = "\n\t$(" . $this->_prep_element($element) . ").{$event}(function(){\n\t\t{$js}\n\t});\n"; + $this->jquery_code_for_compile[] = $event; + return $event; + } + + // -------------------------------------------------------------------- + + /** + * Compile + * + * As events are specified, they are stored in an array + * This funciton compiles them all for output on a page + * + * @access private + * @return string + */ + function _compile($view_var = 'script_foot', $script_tags = TRUE) + { + // External references + $external_scripts = implode('', $this->jquery_code_for_load); + $this->CI->load->vars(array('library_src' => $external_scripts)); + + if (count($this->jquery_code_for_compile) == 0 ) + { + // no inline references, let's just return + return; + } + + // Inline references + $script = '$(document).ready(function() {' . "\n"; + $script .= implode('', $this->jquery_code_for_compile); + $script .= '});'; + + $output = ($script_tags === FALSE) ? $script : $this->inline($script); + + $this->CI->load->vars(array($view_var => $output)); + + } + + // -------------------------------------------------------------------- + + /** + * Clear Compile + * + * Clears the array of script events collected for output + * + * @access public + * @return void + */ + function _clear_compile() + { + $this->jquery_code_for_compile = array(); + } + + // -------------------------------------------------------------------- + + /** + * Document Ready + * + * A wrapper for writing document.ready() + * + * @access private + * @return string + */ + function _document_ready($js) + { + if ( ! is_array($js)) + { + $js = array ($js); + + } + + foreach ($js as $script) + { + $this->jquery_code_for_compile[] = $script; + } + } + + // -------------------------------------------------------------------- + + /** + * Script Tag + * + * Outputs the script tag that loads the jquery.js file into an HTML document + * + * @access public + * @param string + * @return string + */ + function script($library_src = '', $relative = FALSE) + { + $library_src = $this->external($library_src, $relative); + $this->jquery_code_for_load[] = $library_src; + return $library_src; + } + + // -------------------------------------------------------------------- + + /** + * Prep Element + * + * Puts HTML element in quotes for use in jQuery code + * unless the supplied element is the Javascript 'this' + * object, in which case no quotes are added + * + * @access public + * @param string + * @return string + */ + function _prep_element($element) + { + if ($element != 'this') + { + $element = '"'.$element.'"'; + } + + return $element; + } + + // -------------------------------------------------------------------- + + /** + * Validate Speed + * + * Ensures the speed parameter is valid for jQuery + * + * @access private + * @param string + * @return string + */ + function _validate_speed($speed) + { + if (in_array($speed, array('slow', 'normal', 'fast'))) + { + $speed = '"'.$speed.'"'; + } + elseif (preg_match("/[^0-9]/", $speed)) + { + $speed = ''; + } + + return $speed; + } + +} + +/* End of file Jquery.php */ +/* Location: ./system/libraries/Jquery.php */ \ No newline at end of file diff --git a/tambahan.txt b/tambahan.txt new file mode 100644 index 0000000..e0d9849 --- /dev/null +++ b/tambahan.txt @@ -0,0 +1,12 @@ +tabel volume +dealer +area +region +province +month +target +previous_stock +actual +sellout +order +pattern *dropdown \ No newline at end of file